/*************************************************************************** 
 * 
 *		EDROOM SERVICE LIBRARY   
 *    
 *		Copyright (C) 2007-2010  Oscar Rodriguez Polo  
 * 
 *      Contact: opolo@aut.uah.es  
 * 
 ****************************************************************************/

/**************************************************************************** 
 *
 *   This program is free software; you can redistribute it and/or
 *   modify it under the terms of the GNU General Public License
 *   as published by the Free Software Foundation; either version 2 
 *   of the License, or (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program; if not, write to the Free Software
 *   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
 *
 *
 ****************************************************************************/


/*!
 * \brief edroom services library cpp
 * 
 * \author Oscar Rodrguez Polo
 * \date $Date: 2010-02-15 10:09:39 $
 * \Version $Revision: 1.1.4.3 $
 */


#include <edroomsl/edroomsl.h>
#include <public/edroomsl_types.h>
#include <edroomsl/edroomtc.h>
//#include <public/debug_primitives.h>


/*************************************************************************** 
 *************************************************************************** 
 * 
 *					TARGET OPTIONS DEFINES   
 *    
 *************************************************************************** 
 ****************************************************************************/

//!This code is affected for the following defines

/*************************************************************************** 
 *		DEFINES THAT EDROOM AUTOMATICALLY GENERATES
 *
 *	EDROOM automatically configure this defines in the edroomdf.h file
 *
 * _EDROOM_IS_EMBEDDED_		Embedded C++ compliant: do not use malloc nor template
 *
 * _EDROOM_IS_DEBUG_		Add debug and trace information
 *  
 * _EDROOM_HAND_EXCEP_		Handle Exceptions
 *
 *
 ****************************************************************************/

/*************************************************************************** 
 *		DEFINES THAT MUST BE SET IN THE EDROOM CONFIG TARGET FILE edroomtc.h 
 *
 *	_EDROOM_SYSTEM_CLOSE		Set this define the system must close 
 *
 *	_EDROOM_MainMustWait		Set this define it's needed the main function 
 * 								must wait util all the tasks have finished before
 *								return
 *								
 *  _EDROOM_HANDLE_IRQS			Use this define if it's needed handle IRQs
 *
 *
 ****************************************************************************/

/*************************************************************************** 
 *		DEFINES TO TEST SOME SCHEDULING FACTS
 *		THEY MUST BE SET IN THE EDROOM CONFIG TARGET FILE edroomtc.h 
 *  	Only active the to test some characteristics of the EDROOM scheduling 
 *		service, the performance can decrease if you activate them
 *
 *
 *  _EDROOM_NO_INHERIT_MSG		Set if it is not used the inheritance 
 *								of the message priority between actors
 *
 *	_EDROOM_URGENT_INVOKE		Set if the invoke will be always URGENT
 * 
 *	_EDROOM_INTERNAL_EVENT_RESTORE_PRIO	Set if internal events restore
 *								the priority
 * 
 * _EDROOM_INFORM_AT_NO_NEED_WAIT Set if InformAt does not need wait
 *
 ****************************************************************************/



/*!
 * \brief CEDROOMMemory cpp (edroom services library) 
 * 
 * \author Oscar Rodrguez Polo
 * \date $Date: 2010-02-15 10:09:17 $
 * \Version $Revision: 1.1.4.4 $
 * 
 * $Log: edroommemory.cpp,v $
 * Revision 1.1.4.4  2010-02-15 10:09:17  opolo
 * actualizados los nombres de los archivos y servicios
 *
 * Revision 1.1.4.3  2006/11/09 15:18:19  opolo
 * Rename the classes that manage the pools
 *
 * Revision 1.1.4.2  2006/10/18 18:31:51  opolo
 * Add Log
 *
 *
 * Revision 1.1.4.1  2006/10/18 18:07:20  opolo
 * *** empty log message ***
 * 
 */



//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// class CEDROOMMemoryPool
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++


//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// CONSTRUCTOR
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

void CEDROOMMemoryPool::SetMemory(TEDROOMUInt32 dimension
								,void * pDataMemory
								,TEDROOMBool * pMarksMemory
								,TEDROOMUInt32 elementSize){

			TEDROOMUInt32 l_n;

			if (dimension==0 || elementSize==0)
				{
				NextFreeIndex=EDROOMUINT32_MAX;	//Is empty
				PDataMemory=NULL;

				}
			else{
				 //Init PDataMemory	
				 PDataMemory=(TEDROOMByte *)pDataMemory;

				 //Init Free Marks
				 PFreeMarks=pMarksMemory;

				 for (l_n=0;l_n<dimension;l_n++)
					*(PFreeMarks + l_n)=true;  // All are Free

				 //Init Size
				 ElementSize=elementSize;

				 //Init Dimension
				 Dimension=dimension;
				 
				 //Init FreeIndex
             	 NextFreeIndex=0;

			}
	 }

TEDROOMUInt32 CEDROOMMemoryPool::GetElementSize(void)
{
	return ElementSize;
}

//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// AllocData
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

TEDROOMByte * CEDROOMMemoryPool::AllocData(){

		TEDROOMUInt32 l_elemindex;
		//Call to AllocData with index
		return AllocData(l_elemindex);

}


//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// AllocData
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++


TEDROOMByte * CEDROOMMemoryPool::AllocData(TEDROOMUInt32 & rElemIndex){

			TEDROOMByte *l_new;
			TEDROOMUInt32 l_counter,l_index;

			//Check if there is any element free
			if (NextFreeIndex==EDROOMUINT32_MAX){

				//None element free
				l_new=NULL;
				rElemIndex=EDROOMUINT32_MAX;

#ifdef _EDROOM_IS_DEBUG_

				EDROOMFError <<"POOL Empty";
				EDROOMFError.close();
//				exit(1);

#endif

			}
			else {

				// Pointer to the free element
				l_new=PDataMemory+(NextFreeIndex*ElementSize); 
				
				// Mark the element as not free
				*(PFreeMarks+NextFreeIndex)=false; 
				rElemIndex=NextFreeIndex;

				// Look for another free element,
				l_counter=0;
				l_index=NextFreeIndex;
				NextFreeIndex=EDROOMUINT32_MAX;
				
				do{
					//next index 
					l_index=(l_index + 1 +l_counter)%Dimension;   

					if(*(PFreeMarks+l_index)){
						
						//It is free
						NextFreeIndex=l_index;
					}
					l_counter++;
				
				}while((l_counter<Dimension)&&(NextFreeIndex==EDROOMUINT32_MAX));

			} 

			return(l_new);
}


//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// FreeData
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++


TEDROOMInt8 CEDROOMMemoryPool::FreeData(void * pData){
	
		TEDROOMInt8 l_error;
		TEDROOMByte* l_pAux;

		TEDROOMUInt64 l_position,l_dimensionUInt64;
		TEDROOMUInt32 l_index;

		l_pAux=(TEDROOMByte*)pData;

		  //It is needed to work with UInt64  
		l_position = (l_pAux-PDataMemory)/ElementSize;
		  
		l_dimensionUInt64=Dimension;

		if ((l_position <0)||(l_position >= l_dimensionUInt64)){

		  				//It does not 

				l_error=-1;

#ifdef _EDROOM_IS_DEBUG_

				EDROOMFError <<"POOL Free Error, Element out of Pool";
				EDROOMFError.close();
				//exit(1);

#endif

		}
		else{

				//It is checked that is less than Dimension and > 0
				l_index=(TEDROOMUInt32) l_position; 
													

#ifdef _EDROOM_IS_DEBUG_

				if(*(PFreeMarks+l_index)){
						//the element was free
						l_error=-2;
					
				}else
				
#endif 
				
				//Mark as free
				*(PFreeMarks+l_index)=true;  
				
				//If the pool was empty
				if (NextFreeIndex==EDROOMUINT32_MAX)
					NextFreeIndex=l_index;

				pData=NULL; // pData returns with NULL

				l_error=0;

		}
		return (l_error);
}



//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// class CEDROOMProtectedMemoryPool
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// CONSTRUCTOR
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

 CEDROOMProtectedMemoryPool::CEDROOMProtectedMemoryPool(TEDROOMUInt32 dimension, 
 													void * pDataMemory, 
 													TEDROOMBool * pMarksMemory,  
 													TEDROOMUInt32 elementSize)

 #ifdef _EDROOM_IS_DEBUG_

	:Mutex("Pool Mutex Semaphore")

 #endif

 {
 	SetMemory(dimension, pDataMemory, pMarksMemory,  elementSize);
 
 }


//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// AllocData
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

TEDROOMByte * CEDROOMProtectedMemoryPool::AllocData(){

		TEDROOMUInt32 l_elemindex;
		//Call to AllocData with index
		return AllocData(l_elemindex);

}


//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// AllocData
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

TEDROOMByte * CEDROOMProtectedMemoryPool::AllocData(TEDROOMUInt32 & rElemIndex){


			TEDROOMByte *l_pData;

			Mutex.Wait(); 

			l_pData=CEDROOMMemoryPool::AllocData(rElemIndex);

			Mutex.Signal(); 

			return(l_pData);
}


//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// FreeData
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++


TEDROOMInt8 CEDROOMProtectedMemoryPool::FreeData(void * pData){


		  	TEDROOMInt8 l_error;
			
			Mutex.Wait(); 

			l_error=CEDROOMMemoryPool::FreeData(pData);

			Mutex.Signal(); 

			return l_error;

}



/*!
 * \brief edroommessage cpp (edroom services library) 
 * 
 * \author Oscar Rodrguez Polo
 * \date $Date: 2010-03-04 09:08:17 $
 * \Version $Revision: 1.1.4.5 $
 *
 * $Log: edroommessage.cpp,v $
 * Revision 1.1.4.5  2010-03-04 09:08:17  opolo
 * Changed the names of the attributes
 *
 * Revision 1.1.4.4  2010-02-15 10:09:17  opolo
 * actualizados los nombres de los archivos y servicios
 *
 * Revision 1.1.4.3  2006/11/09 15:23:12  opolo
 * Use the new name of the classes that manage the pools
 * 	EDROOMPool EDROOMMemoryPool and EDROOMProtectedMemoryPool
 *
 * Revision 1.1.4.2  2006/10/18 18:31:51  opolo
 * Add Log
 *
 *
 * Revision 1.1.4.1  2006/10/18 18:07:20  opolo
 * *** empty log message ***
 * 
 */


//*************************************************************************
//******************FUNCIONES MIEMBRO PUBLICAS DE CEDROOMMessage *************


//*************************************************************************
//CONSTRUCTOR

CEDROOMMessage::CEDROOMMessage(){

	mp_MsgPool=NULL; 
	mp_DataPool=NULL; 
					
}

//*************************************************************************
//IsCancelled

TEDROOMBool CEDROOMMessage::IsCancelled(){return false;} // No se cancelan los mensajes corrientes
											  // Solo los de Timeout


//*************************************************************************
//CEDROOMInterface

CEDROOMInterface   * CEDROOMMessage::GetPInterface (){
	return(mp_Interface);

}

TEDROOMWord32 CEDROOMMessage::GetMsgDataSize() {
	return mp_DataPool->GetElementSize();
}


//*************************************************************************
//reply

void CEDROOMMessage::reply(TEDROOMSignal signal){

	// Lo mando con la misma prioridad que
	 
	mp_Interface->send(signal,priority);
}
//**************************************************************************

void CEDROOMMessage::reply(TEDROOMSignal signal, void *dataObjetPtr
													, CEDROOMPool *apManMemDat){

	//Lo mando con la misma prioridad que el mensaje enviado

	mp_Interface->send(signal,priority,dataObjetPtr,apManMemDat);
}

//**************************************************************************

void CEDROOMMessage::reply(CEDROOMMessage *Msg){

	//Lo mando con la misma prioridad que el mensaje enviado

	mp_Interface->send(Msg->signal,Msg->priority,Msg->data,Msg->mp_DataPool);
}

//**************************************************************************

void CEDROOMMessage::reply(TEDROOMSignal signal, CEDROOMMessage *Msg){

	//Lo mando con la misma prioridad que el mensaje enviado

	mp_Interface->send(signal,priority,Msg->data,Msg->mp_DataPool);

	Msg->data=NULL;
}

//*************************************************************************
//******************FUNCIONES AMIGAS DE CEDROOMMessage ***********************

//*************************************************************************
//EDROOMFreeMessage

void EDROOMFreeMessage(CEDROOMMessage *&apMsg){
	//Compruebo que el apuntador es distinto de NULL

	if (apMsg){

		if (apMsg->data){       //Si hay algun dato en el mensaje
			if(apMsg->mp_DataPool)
				apMsg->mp_DataPool->FreeData(apMsg->data); //

		}
		//Si hay manejador de memoria para el mensaje se utiliza
		
		void *auxApMsg=apMsg;

		if(apMsg->mp_MsgPool)
			apMsg->mp_MsgPool->FreeData(auxApMsg); //apuntador al manejador de memoria de los Mensajes

			
		apMsg=NULL; //Ya se ha liberado la memoria

	}
}

void EDROOMFreeMsgBack(CEDROOMMessage *&apMsg){
					//Compruebo que el apuntador es distinto de NULL

	if (apMsg){

		if (apMsg->data){       //Si hay algun dato en el mensaje
			if(apMsg->mp_DataPool)
				apMsg->mp_DataPool->FreeData(apMsg->data); //

      
		}
		apMsg=NULL; //Ya se ha liberado la memoria

	}
}



//*************************************************************************
//******************FUNCIONES MIEMBRO PUBLICAS DE CEDROOMSynchrMessage ******


//*************************************************************************
//CONSTRUCTOR


#ifdef _EDROOM_IS_DEBUG_

CEDROOMSynchrMessage::CEDROOMSynchrMessage():m_SynchrSem("Synchr Sem",0){
		mp_MsgBack=NULL;
}
#else
CEDROOMSynchrMessage::CEDROOMSynchrMessage():m_SynchrSem(0){
		mp_MsgBack=NULL;
}

#endif



//*************************************************************************
//reply()



void CEDROOMSynchrMessage::reply(TEDROOMSignal signal){

	CEDROOMSynchrMessage::reply(signal,NULL,NULL);

}

//**************************************************************************

void CEDROOMSynchrMessage::reply(TEDROOMSignal signal, void *dataObjetPtr
												, CEDROOMPool *apManMemDat){

	if(m_IsSenderWaiting){

		mp_MsgBack->signal=mp_Interface->applyConverFunct(signal); // Completo el mensaje
		mp_MsgBack->data=dataObjetPtr;
		mp_MsgBack->mp_DataPool=apManMemDat;

		m_IsSenderWaiting=false; // No debe esperar mas
		m_SynchrSem.Signal(); //Seala al emisor para que prosiga
	}

}
//**************************************************************************

void CEDROOMSynchrMessage::reply(TEDROOMSignal signal, CEDROOMMessage *Msg){

	CEDROOMSynchrMessage::reply(signal,Msg->data,Msg->mp_DataPool);

	Msg->data=NULL;
}

//**************************************************************************

void CEDROOMSynchrMessage::reply(CEDROOMMessage *Msg){

	CEDROOMSynchrMessage::reply(Msg->signal,Msg->data,Msg->mp_DataPool);

	Msg->data=NULL;
}

//**************************************************************************


//*************************************************************************
//******************FUNCIONES MIEMBRO PRIVADAS DE CEDROOMTimeOutMessage ******

//*************************************************************************
//cancelled()

TEDROOMBool CEDROOMTimeOutMessage::IsCancelled(){
	bool cancl;

	mp_Mutex->Wait(); //Capturo la exclusion mutua

	if(mp_TimerInfo){

		if(mp_TimerInfo->m_State==edroomTimerCancelled)
			 cancl=1;
		else
			cancl=0;

		void * aux_void_pTimerInf= mp_TimerInfo;
	

		mp_TimerInfoPool->FreeData(aux_void_pTimerInf);  // Devuelve la memoria

		mp_TimerInfo=NULL;		

	}
	else
		cancl=1; // Si no hay puntero al status ha habido un error
					// consideramos que el mensaje esta cancelado

	mp_Mutex->Signal(); //Libero la exclusion mutua
	return(cancl);
}

//*************************************************************************



//*******************************************************************************
//******************FUNCIONES MIEMBRO PUBLICAS DE CEDROOMSynchrMessagesPool ******


// Constructor


#ifdef _EDROOM_IS_DEBUG_

CEDROOMSynchrMessagesPool::CEDROOMSynchrMessagesPool(
									CEDROOMSynchrMessage *  pSynMsg)
									:m_Mutex("Mutex Sem ",1){

#else

CEDROOMSynchrMessagesPool::CEDROOMSynchrMessagesPool(
									CEDROOMSynchrMessage *  pSynMsg)
									:m_Mutex(1){

#endif

		mp_SynchrMsg=pSynMsg;

}

TEDROOMUInt32 CEDROOMSynchrMessagesPool::GetElementSize()
{
	return sizeof (CEDROOMSynchrMessage);
}

//	 AllocData


CEDROOMSynchrMessage *  CEDROOMSynchrMessagesPool::AllocData(void){

		m_Mutex.Wait();
		return mp_SynchrMsg; //Semaforo para la sincronizacion del mensaje

	}


TEDROOMInt8 CEDROOMSynchrMessagesPool::FreeData(void * apunt){

				m_Mutex.Signal();
				return 0;
}


		
void CEDROOMMessagesPool::SetMemory(TEDROOMUInt32 dimension
											, CEDROOMMessage * pMessagePool
  											, TEDROOMBool * pMemoryMarks){


	CEDROOMMemoryPool::SetMemory(dimension, pMessagePool
										, pMemoryMarks, sizeof (CEDROOMMessage));

}

CEDROOMMessage * CEDROOMMessagesPool::AllocData(){

				return (CEDROOMMessage * )CEDROOMMemoryPool::AllocData();

}

	
void CEDROOMTimeOutMessagesPool::SetMemory(TEDROOMUInt32 elemNumber, CEDROOMTimeOutMessage* pDataPool,TEDROOMBool * pPoolMarks){

	CEDROOMMemoryPool::SetMemory(elemNumber,pDataPool, pPoolMarks, sizeof (CEDROOMTimeOutMessage));

}

	   
CEDROOMTimeOutMessage * CEDROOMTimeOutMessagesPool::AllocData(){

				return (CEDROOMTimeOutMessage * )CEDROOMMemoryPool::AllocData();
}

#ifdef _EDROOM_IS_DEBUG_

CEDROOMRemoteSynchrMessagesPool::CEDROOMRemoteSynchrMessagesPool(
									CEDROOMRemoteSynchrMessage *  pSynMsg)
									:m_Mutex("Mutex Sem ",1) {

#else

CEDROOMRemoteSynchrMessagesPool::CEDROOMRemoteSynchrMessagesPool(
									CEDROOMRemoteSynchrMessage *  pSynMsg)
									:m_Mutex(1)
{
#endif
		mp_SynchrMsg=pSynMsg;
}


TEDROOMUInt32 CEDROOMRemoteSynchrMessagesPool::GetElementSize()
{
	return sizeof (CEDROOMRemoteSynchrMessage);
}

//	 AllocData


CEDROOMRemoteSynchrMessage *  CEDROOMRemoteSynchrMessagesPool::AllocData(void){

		m_Mutex.Wait();
		return mp_SynchrMsg; //Semaforo para la sincronizacion del mensaje

	}


TEDROOMInt8 CEDROOMRemoteSynchrMessagesPool::FreeData(void * apunt){

				m_Mutex.Signal();
				return 0;
}

//*************************************************************************
//CONSTRUCTOR

CEDROOMRemoteSynchrMessage::CEDROOMRemoteSynchrMessage()
{
    p_MsgBack=NULL;
}

//*************************************************************************
//reply()

void CEDROOMRemoteSynchrMessage::reply(TEDROOMSignal signal)
{
    CEDROOMRemoteSynchrMessage::reply(signal,NULL,NULL);
}

//**************************************************************************

void CEDROOMRemoteSynchrMessage::reply(TEDROOMSignal signal, void *dataObjectPtr,
                                      CEDROOMPool *apManMemDat)
{
    ((CEDROOMRemoteTXChannel *)(mp_Interface->mp_Channel))->reply(signal, priority, dataObjectPtr, apManMemDat);
}
//**************************************************************************

void CEDROOMRemoteSynchrMessage::reply(TEDROOMSignal signal, CEDROOMMessage *Msg)
{

    CEDROOMRemoteSynchrMessage::reply(signal,Msg->data,Msg->mp_DataPool);

    Msg->data=NULL;
}

//**************************************************************************

void CEDROOMRemoteSynchrMessage::reply(CEDROOMMessage *Msg){

    CEDROOMRemoteSynchrMessage::reply(Msg->signal,Msg->data,Msg->mp_DataPool);

    Msg->data=NULL;
}




/*!
 * \brief CEDROOMInterface cpp (edroom services library) 
 * 
 * \author Oscar Rodrguez Polo
 * \date $Date: 2010-03-04 09:08:17 $
 * \Version $Revision: 1.1.4.5 $
 *
 * $Log: edroominterface.cpp,v $
 * Revision 1.1.4.5  2010-03-04 09:08:17  opolo
 * Changed the names of the attributes
 *
 * Revision 1.1.4.4  2010-02-15 10:09:17  opolo
 * actualizados los nombres de los archivos y servicios
 *
 * Revision 1.1.4.3  2006/11/09 15:23:12  opolo
 * Use the new name of the classes that manage the pools
 * 	CEDROOMPool EDROOMMemoryPool and EDROOMProtectedMemoryPool
 *
 * Revision 1.1.4.2  2006/10/18 18:31:51  opolo
 * Add Log
 *
 *
 * Revision 1.1.4.1  2006/10/18 18:07:20  opolo
 * *** empty log message ***
 * 
 */


//*****************************************************************************************
//********************************** DENINICION DE LAS FUNCIONES MIEMBRO DE ***************
//********************************************CEDROOMInterface ********************************

#ifdef _EDROOM_IS_DEBUG_

const char * EDROOMErrorCommNames[8] =  { "EDROOMNoErrorComm", "EDROOMEmptyPoolMens", "EDROOMSignalInvalidate", "EDROOMFullQueueMens",
							"EDROOMInterfaceDisconnected", "EDROOMCommTimeOut", "EDROOMMsgBackUsed", "EDROOMInterblock" };

#endif

//*****************************************************************************************
//************************************CONSTRUCTOR ********************************

#ifdef _EDROOM_IS_DEBUG_

CEDROOMInterface::CEDROOMInterface(){

		m_IsRegistered=0;  //No esta registrado
		m_IsConnected=0; // No esta connected

}
#endif

//*****************************************************************************************
//************************************CEDROOMInterface::send ********************************



	// VERSION 2.
	// Revisada y comentada
#ifdef _EDROOM_IS_DEBUG_

TEDROOMCommError CEDROOMInterface::send (TEDROOMSignal signal, TEDROOMPriority priority){

	TEDROOMCommError error=EDROOMNoErrorComm;

	// Ver si hay errores
	// Si hay errores el mensaje no se manda

	if (!m_IsConnected){

		error= EDROOMInterfaceDisconnected;

	}else   mp_Channel->send(signal,priority,NULL,NULL);

	if (error!=EDROOMNoErrorComm){
		EDROOMFError <<EDROOMName << " " << EDROOMErrorCommNames[error];
		EDROOMFError.close();
		//exit(1);
	}

	return error;

}

#else

void CEDROOMInterface::send (TEDROOMSignal signal, TEDROOMPriority priority){

	mp_Channel->send(signal,priority,NULL,NULL);

}

#endif



	// VERSION 3.
	// Revisada y comentada

#ifdef _EDROOM_IS_DEBUG_

TEDROOMCommError CEDROOMInterface::send (TEDROOMSignal signal, TEDROOMPriority priority, void * dataObjetPtr,CEDROOMPool * apMemDats){

	TEDROOMCommError error=EDROOMNoErrorComm;

	// Ver si hay errores
	// Si hay errores el mensaje no se manda

	if (!m_IsConnected){

		error= EDROOMInterfaceDisconnected;

	}else
		mp_Channel->send(signal,priority,dataObjetPtr,apMemDats);

	if (error!=EDROOMNoErrorComm){
		EDROOMFError <<EDROOMName << " " <<EDROOMErrorCommNames[error];
		EDROOMFError.close();
		//exit(1);
	}

	return error;


}
#else

void CEDROOMInterface::send (TEDROOMSignal signal, TEDROOMPriority priority, 
						void * dataObjetPtr,CEDROOMPool * apMemDats){

		mp_Channel->send(signal,priority,dataObjetPtr,apMemDats);

}

#endif





	// VERSION 4.
	// Revisada y comentada

#ifdef _EDROOM_IS_DEBUG_

TEDROOMCommError	CEDROOMInterface::send (TEDROOMSignal signal,TEDROOMPriority priority,CEDROOMMessage *message){  // reenvio de un mensaje

	TEDROOMCommError error=EDROOMNoErrorComm;

	// Ver si hay errores
	// Si hay errores el mensaje no se manda

	if (!m_IsConnected){

		error= EDROOMInterfaceDisconnected;

	}else {
		mp_Channel->send(signal,priority,message->data,message->mp_DataPool);
		message->data=NULL;
	}

	if (error!=EDROOMNoErrorComm){
		EDROOMFError <<EDROOMName << " " <<EDROOMErrorCommNames[error];
		EDROOMFError.close();
		//exit(1);
	}

	return error;


}

TEDROOMCommError	CEDROOMInterface::send(TEDROOMSignal signal,CEDROOMMessage *message){  // reenvio de un mensaje

		return send(signal,message->priority,message);

}

TEDROOMCommError	CEDROOMInterface::send(CEDROOMMessage *message){  // reenvio de un mensaje

		return send(message->signal,message->priority,message);

}

#else

void	CEDROOMInterface::send(TEDROOMSignal signal,TEDROOMPriority priority,CEDROOMMessage *message){  // reenvio de un mensaje

	mp_Channel->send(signal,priority,message->data,message->mp_DataPool);
	message->data=NULL;

}

void	CEDROOMInterface::send(TEDROOMSignal signal,CEDROOMMessage *message){  // reenvio de un mensaje

	send(signal,message->priority,message);

}

void	CEDROOMInterface::send(CEDROOMMessage *message){  // reenvio de un mensaje

	send(message->signal,message->priority,message);

}


#endif


//*****************************************************************************************
//************************************CEDROOMInterface::invoke ********************************




CEDROOMMessage * CEDROOMInterface::invoke(TEDROOMSignal signal,TEDROOMPriority priority){

	return invoke(signal,priority, NULL, NULL);
}



//*****************************************************************************************
//************************************CEDROOMInterface::invoke ********************************


CEDROOMMessage * CEDROOMInterface::invoke(TEDROOMSignal signal, void *dataObjetPtr
												, CEDROOMPool * apMemDats){

	return invoke(signal, EDROOMprioURGENT, dataObjetPtr,apMemDats);

}



CEDROOMMessage * CEDROOMInterface::invoke(TEDROOMSignal signal, TEDROOMPriority priority
								, void *dataObjetPtr, CEDROOMPool * apMemDats){


#ifdef _EDROOM_IS_DEBUG_

	TEDROOMCommError error=EDROOMNoErrorComm;

	// Ver si hay errores
	// Si hay errores el mensaje no se manda

	if (!m_IsConnected){

		error= EDROOMInterfaceDisconnected;

    	EDROOMFError <<EDROOMName << " " <<EDROOMErrorCommNames[error];
		EDROOMFError.close();
		//exit(1);
	}

#endif
		return mp_Channel->invoke(signal,priority,dataObjetPtr, apMemDats);



}


//*****************************************************************************************
//************************************CEDROOMInterface::invokeForward ********************************


CEDROOMMessage * CEDROOMInterface::invoke(TEDROOMSignal signal, TEDROOMPriority priority, CEDROOMMessage *message){

		CEDROOMMessage * msgBack;
		msgBack=invoke(signal,priority,message->data,message->mp_DataPool);
		message->data=NULL;

		return (msgBack);

}

CEDROOMMessage * CEDROOMInterface::invoke(TEDROOMSignal signal, CEDROOMMessage *message){

	return invoke(signal,message->priority,message);

}

CEDROOMMessage * CEDROOMInterface::invoke(CEDROOMMessage *message){

	return invoke(message->signal,message->priority,message);
}



TEDROOMSignal CEDROOMInterface::applyConverFunct(TEDROOMSignal signal_){

	return mp_Channel->mp_SenderToReceiverSignalTranslator(signal_);

}


//identity test functions:

TEDROOMBool CEDROOMInterface::operator ==(CEDROOMInterface &rEDROOMInterface){
		return (m_IdInterface==rEDROOMInterface.m_IdInterface);
	}

TEDROOMBool CEDROOMInterface::operator !=(CEDROOMInterface &rEDROOMInterface){
		return (m_IdInterface!=rEDROOMInterface.m_IdInterface);
	}



#ifdef _EDROOM_HANDLE_IRQS

//**************************************************************************
//********* CEDROOMInterfaceIRQ ***********************************************

void CEDROOMIRQInterface::InstallHanler(){
		if(!IRQInstalled) {
			Pr_IRQManager::Install(HandIRQ,IRQ);
			Pr_IRQManager::Enable(IRQ);
			IRQInstalled=1;
		}

}

void CEDROOMIRQInterface::DeInstallHanler(){
		if(IRQInstalled) {
			Pr_IRQManager::Disable(IRQ);
			Pr_IRQManager::Install(HandIdle,IRQ);
			Pr_IRQManager::Enable(IRQ);
			IRQInstalled=0;

		}
}

void CEDROOMIRQInterface::EndIRQHandlerTask(){

							Pr_IRQManager::Disable(IRQ);
							EndIRQLook->Signal();
							IRQEventLook->Signal();


}

CEDROOMIRQInterface::CEDROOMIRQInterface(	Pr_IRQHandler HandIRQ_
											,Pr_IRQHandler HandIdle_
											,Pr_IRQEvent &IRQEventLook_ 
											,Pr_SemaphoreBin & EndIRQLook_
											,TEDROOMPriority prio
											,TEDROOMInt8 IRQ_){

						HandIRQ= HandIRQ_;
						HandIdle =HandIdle_;
						EndIRQLook= &EndIRQLook_;
						IRQEventLook= &IRQEventLook_;
						priority=prio;
						IRQInstalled=0;
						IRQ=IRQ_;
}


void	CEDROOMIRQInterface::NewIRQMsg(TEDROOMSignal signal, void * dataObjetPtr
			, CEDROOMPool * pDataPool){

		CEDROOMMessage *apMsg;


								// Apuntador a un objeto de la clase Pr_Task que
								  // representa la tarea que realiza el comportamiento
								  // del Component

		mp_Component->m_Mutex.Wait();


#ifdef _EDROOM_NO_INHERIT_MSG

		mp_Component->m_ComponentTask.SetMaxPrioMsg( priority);

#else

		mp_Component->PrioInheritanceInSendMsg(priority);

#endif

		// Reservar memoria para el mensaje

		apMsg=mp_Component->mp_MsgPool->AllocData();

		// Rellenar sus campos;

		// Seal

		apMsg->signal=signal;

		//apuntador al manejador de memoria de los Mensajes del Receptor
		 //apuntador al manejador de memoria de los Mensajes

		apMsg->mp_MsgPool=mp_Component->mp_MsgPool;

		//dato enviado
		apMsg->data=dataObjetPtr;

		//manejador de memoria
		apMsg->mp_DataPool=pDataPool;

		//Prioridad del mensaje

		apMsg->priority=priority;

		//Completo el campo interf para que apunte al puerto por el que se recibe
		// el mensaje
		apMsg->mp_Interface=this;

		// Se mete el mensaje en la cola asociada a este puerto.

		mp_Component->m_MsgQueue.In(apMsg);


		mp_Component->m_Mutex.Signal();

	}

#endif

/*!
 * \brief edroomtiming header (edroom services library) 
 * 
 * \author Oscar Rodrguez Polo
 * \date $Date: 2010-03-04 09:08:17 $
 * \Version $Revision: 1.1.4.5 $
 * 
 * $Log: edroomtiming.cpp,v $
 * Revision 1.1.4.5  2010-03-04 09:08:17  opolo
 * Changed the names of the attributes
 *
 * Revision 1.1.4.4  2010-02-15 10:09:17  opolo
 * actualizados los nombres de los archivos y servicios
 *
 * Revision 1.1.4.3  2006/11/09 15:21:40  opolo
 * Define the CEDROOMTimingInterface class
 * Use the new name of the classes that manage the pools
 * 	CEDROOMPool EDROOMMemoryPool and EDROOMProtectedMemoryPool
 *
 * Revision 1.1.4.2  2006/10/18 18:31:51  opolo
 * Add Log
 *
 *
 * Revision 1.1.4.1  2006/10/18 18:07:20  opolo
 * *** empty log message ***
 * 
 */


//*********************************************************************
//*********************************************************************
// class CEDROOMTimer


CEDROOMTimer::CEDROOMTimer(){m_Index=EDROOMUINT32_MAX;}  // Se inicializa el Index a UINT_MA

TEDROOMBool CEDROOMTimer::IsValid(){return (TEDROOMBool) (m_Index < EDROOMUINT32_MAX);}



//*********************************************************************
//*********************************************************************
// class CEDROOMTimingInterface

//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// CONSTRUCTOR
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

#ifdef __EDROOMSL_2010
CEDROOMTimingInterface::CEDROOMTimingInterface( CEDROOMTimingSAP * pTimingSAP
													,TEDROOMUInt32 maxNumTimers
													,Pr_Time minPeriod){

		PTimingSAP=pTimingSAP;
		
		MinPeriod=minPeriod;
		
		MaxNumTimers=maxNumTimers;

   		FreeTimers=MaxNumTimers;

   		LastTimeout=0;

														
}														

#else

CEDROOMTimingInterface::CEDROOMTimingInterface( CEDROOMTimingSAP * pTimingSAP
													,TEDROOMUInt32 maxNumTimers
													){

		mp_TimingSAP=pTimingSAP;
		
		m_MaxNumTimers=maxNumTimers;

														
}														

#endif														

//**********************************************************************
//funcion miembro       cancelTimer

void  CEDROOMTimingInterface::cancelTimer(CEDROOMTimer &rTimerId){
	
	mp_TimingSAP->cancelTimer(this,rTimerId);

}


//**********************************************************************
//funcion miembro       InformAt

CEDROOMTimer       CEDROOMTimingInterface::InformAt(Pr_Time timeValue
									,TEDROOMPriority MsgPrio
									,void *data, CEDROOMPool * bloqueMemData){

#ifdef __EDROOMSL_2010		

	CEDROOMTimer	lTimerId;
	//if(FreeTimers){
		//FreeTimers--;
		if(LastTimeout>0){
			LastTimeout+=MinPeriod;
			if(timeValue<LastTimeout)
				timeValue=LastTimeout;
		}
		LastTimeout=timeValue;
		lTimerId=mp_TimingSAP->InformAt(this,timeValue,MsgPrio,data,bloqueMemData);
		
	//}else
		//lTimerId.m_Index=EDROOMUINT32_MAX;
	
	return(lTimerId);   // devuelve el identificador
						// del timer creado

#else

	return mp_TimingSAP->InformAt(this,timeValue,MsgPrio,data,bloqueMemData);
	

#endif		


}


//**********************************************************************
//funcion miembro       InformAt


CEDROOMTimer       CEDROOMTimingInterface::InformAt(Pr_Time timeValue,TEDROOMPriority MsgPrio){

#ifdef __EDROOMSL_2010		
	return (InformAt(timeValue,MsgPrio,NULL,NULL));   // devuelve el identificador
																// del timer creado
#else
	return (mp_TimingSAP->InformAt(this,timeValue,MsgPrio,NULL,NULL));   // devuelve el identificador
																// del timer creado
#endif															  
}


//**********************************************************************




// relative timing functions:

//**********************************************************************
//funcion miembro       InformIn

CEDROOMTimer CEDROOMTimingInterface::InformIn(Pr_Time timeoutValue
													,TEDROOMPriority MsgPrio){

	 Pr_Time time;

	 time.GetTime(); // Tomo el tiempo Actual
			
	 time+=timeoutValue;

#ifdef __EDROOMSL_2010

	 return(InformAt(time,MsgPrio,NULL,NULL));   // devuelve el identificador

#else
	return (mp_TimingSAP->InformAt(this,time,MsgPrio,NULL,NULL));   // devuelve el identificador

#endif															  

}

//**********************************************************************

//**********************************************************************
//funcion miembro       InformIn


CEDROOMTimer CEDROOMTimingInterface::InformIn(Pr_Time timeoutValue
						, TEDROOMPriority MsgPrio
						, void *data, CEDROOMPool * bloqueMemData){


	 Pr_Time time;

	 time.GetTime(); // Tomo el tiempo Actual

	 time+=timeoutValue;

#ifdef __EDROOMSL_2010

	return(InformAt(time,MsgPrio,data,bloqueMemData));   // devuelve el identificador

#else
	return (mp_TimingSAP->InformAt(this,time,MsgPrio,data,bloqueMemData));   // devuelve el identificador

#endif															  
															  
}

//**********************************************************************
//       currentTime

void CEDROOMTimingInterface::currentTime(Pr_Time &time){time.GetTime();}


//**********************************************************************
//       currentTime

Pr_Time CEDROOMTimingInterface::currentTime()
{
	Pr_Time time;
	time.GetTime();
	return time;

}


//*********************************************************************
//*********************************************************************
// class CEDROOMTimingSAP


//**********************************************************************
// CONSTRUCTOR


CEDROOMTimingSAP::CEDROOMTimingSAP(CEDROOMComponent * p_Component_,unsigned int maxNumTimers,CEDROOMTimingMemory *pTimingMemory):


#ifdef _EDROOM_IS_DEBUG_

			m_Mutex("Timming Mutex"),

			m_SynchrSem("TimmingSemWaitTimed",0),

			m_TimerTask(EDROOMfunTimer,  "Tarea_timer", EDROOMprioURGENT, _EDROOM_TIMING_TASK_STACK)

			,m_WaitComponentSem("TimmingSemWaitEnd",0)


#else

			m_SynchrSem(0)

			,m_TimerTask(EDROOMfunTimer, EDROOMprioURGENT, _EDROOM_TIMING_TASK_STACK)

			,m_WaitComponentSem(0)
#endif


{


#ifdef _EDROOM_IS_DEBUG_

		if (maxNumTimers>=EDROOMUINT32_MAX)  // El limite es _EDROOM_IS_DEBUG_-1
				maxNumTimers=EDROOMUINT32_MAX-1;

#endif

			mp_TimerTask=&m_TimerTask;

			mp_Component=p_Component_; //Apuntador al component propietario de la clase

			// Semaforo para asegurar la exclusion mutua


#ifdef _EDROOM_SYSTEM_CLOSE

			m_IsSAPFinished=0;

#endif

		  mp_TimerInfoPool=&pTimingMemory->m_TimerInfoMem;

		  mp_TimeOutMsgPool=&pTimingMemory->m_TimeOutMessMem;

		  mp_NextTimer=NULL;



	}





//**********************************************************************
// DESTRUCTOR

#ifdef _EDROOM_SYSTEM_CLOSE

CEDROOMTimingSAP::~CEDROOMTimingSAP(){



		m_Mutex.Wait();

		m_IsSAPFinished=true;

		if(mp_NextTimer){

			mp_NextTimer->m_State=edroomTimerCancelled;

			CEDROOMTimerInfo *aux=mp_NextTimer->mp_Next;

         	mp_Component->m_Mutex.Wait();

			while (aux){

				CEDROOMMessage * auxMsg= (CEDROOMMessage *)aux->mp_Msg;

				EDROOMFreeMessage(auxMsg);

				aux->mp_Msg=NULL;

				CEDROOMTimerInfo *aux2=aux;

				aux=aux->mp_Next;

				mp_TimerInfoPool->FreeData(aux2);


			}

         	mp_Component->m_Mutex.Signal();

			m_Mutex.Signal();

			m_SynchrSem.Signal();

		}

		else{

				//Mandar un Timer dummy


				CEDROOMTimerConfig timerConfig;

				unsigned int indice;
				timerConfig.mp_TimerInfo=mp_TimerInfoPool->AllocData(indice);

				timerConfig.m_Time=0;

				timerConfig.mp_TimerInfo->m_State=edroomTimerDummy;

				mp_NextTimer=NULL;

				m_Mutex.Signal();

				Pr_Send(m_TimerTask,&timerConfig); // manda el dato al timer


		}

		m_WaitComponentSem.Wait();


	}


#endif



//**********************************************************************
// Funcin Amiga funEDROOMTimer que implementa el timer

#ifdef _EDROOM_TASK_POSIX_

	void * CEDROOMTimingSAP::EDROOMfunTimer(void * paramDumy){


#else

	Pr_TaskRV_t CEDROOMTimingSAP::EDROOMfunTimer(Pr_TaskP_t){
#endif


	CEDROOMComponent *pComponent;

	CEDROOMTimingSAP *ptimerSAP;

	//CEDROOMTimerInfo TimerInfo;
	CEDROOMTimerConfig timerConfig;

	Pr_Time currentTime;
	Pr_Time nextTime;

	bool receiveTimerInfo;

	#ifdef _EDROOM_SYSTEM_CLOSE

	bool isTimerSAPFinished;

	#endif

	receiveTimerInfo=true;


	Pr_Receive(&ptimerSAP,sizeof(CEDROOMTimingSAP *)); // Espera a recibir el dato.

    pComponent=ptimerSAP->mp_Component;
				

	//ptimerSAP->m_Mutex.Wait();

	//ptimerSAP->mp_TimerTask->SetPriority(EDROOMprioMINIMUM);

	//ptimerSAP->m_Mutex.Signal();

	do{

		//PABLO
		//WaitTimed en un semaforo binario de sincronizacin del component
		
			//Chequeo todos los puertos de interrupcion 
						
			//Chequeo todos los puertos de temporizacin 

			//if( WaitCond del semaforo de servicio de comunicaciones)
				//Pr_Receive del mensaje e insercion en la cola
				
			

		//END PABLO
		
		if(receiveTimerInfo){
			Pr_Receive(&timerConfig,sizeof(CEDROOMTimerConfig)); // Espera a recibir el dato.

			#ifdef _EDROOM_SYSTEM_CLOSE
         	if (timerConfig.mp_TimerInfo->m_State!=edroomTimerDummy)
   			#endif
   				#ifdef _EDROOM_INFORM_AT_NO_NEED_WAIT
							;
				#else
   						ptimerSAP->m_WaitComponentSem.Signal();
  				#endif


      	}

		receiveTimerInfo=1;


		//SUPRIMIDO, EL EMISOR SIEMPRE DEJA EN URGENTE ESTA TAREA
				//Se coloca a prioridad maxima para evitar ERROR EN EL SERVICIO DEBIDO A UN SWITCH
				//entre tareas

				//ptimerSAP->m_Mutex.Wait();

				//ptimerSAP->mp_TimerTask->SetMaxPrioTmp(EDROOMprioURGENT);

				//ptimerSAP->m_Mutex.Signal();


		// *****************************************************************************************
		// Siempre se ejecuta en prioridad URGENTE por lo que no hay problemas de switch en el siguiente codigo


		currentTime.GetTime();

		// Ver si es necesario esperar

		if (timerConfig.m_Time > currentTime){

			nextTime=timerConfig.m_Time;
			nextTime-=currentTime;

			ptimerSAP->m_SynchrSem.WaitTimed(nextTime);

			currentTime.GetTime();

		}


		ptimerSAP->m_Mutex.Wait();                             // captura la exclusin mutua.


		// SE asegura que el semaforo no queda sealado ya que siempre se seala en exclusion mutua

		ptimerSAP->m_SynchrSem.WaitCond();

		#ifdef _EDROOM_SYSTEM_CLOSE

      	isTimerSAPFinished=ptimerSAP->m_IsSAPFinished;

		if(!isTimerSAPFinished){

		#endif

			// Mira si ha sido cancelado o postpuesto

			if (timerConfig.mp_TimerInfo->m_State==edroomTimerActive){

				//Next Timer
				ptimerSAP->mp_NextTimer=timerConfig.mp_TimerInfo->mp_Next;

			  // Si no lo ha sido, manda el mensaje de timeout.

				timerConfig.mp_TimerInfo->m_State=edroomTimerSent;

				pComponent->m_Mutex.Wait();

              // Cambiar la prioridad de la tarea destino si es menor(ms prioritaria)


      	#ifdef _EDROOM_NO_INHERIT_MSG

		      pComponent->m_ComponentTask.SetMaxPrioMsg( timerConfig.mp_TimerInfo->mp_Msg->priority);
      	#else

		      pComponent->PrioInheritanceInSendMsg(timerConfig.mp_TimerInfo->mp_Msg->priority);
		#endif



		#ifdef _EDROOM_SYSTEM_CLOSE

				if (!pComponent->m_IsFinished)
		#endif
  					pComponent->m_MsgQueue.In(timerConfig.mp_TimerInfo->mp_Msg);


				pComponent->m_Mutex.Signal();


			}else if (timerConfig.mp_TimerInfo->m_State==edroomTimerCancelled){

            	//Take the message
            	CEDROOMMessage * auxMsg= (CEDROOMMessage *)timerConfig.mp_TimerInfo->mp_Msg;

            	//Handle Next Timer

				ptimerSAP->mp_NextTimer=timerConfig.mp_TimerInfo->mp_Next;

            	//Free current Timer
				timerConfig.mp_TimerInfo->mp_Msg=NULL;

				ptimerSAP->mp_TimerInfoPool->FreeData(timerConfig.mp_TimerInfo);


            	//Take component mutex
				pComponent->m_Mutex.Wait();

				EDROOMFreeMessage(auxMsg);

				pComponent->m_Mutex.Signal();

            	//EDROOM_NO_SWITCH_IN_TIMER_CANCEL
   						//ptimerSAP->m_WaitComponentSem.Signal();


			}

			// Cannot be more Cancelled Timers,


			while(receiveTimerInfo && ptimerSAP->mp_NextTimer){

				currentTime.GetTime();

				timerConfig.mp_TimerInfo=ptimerSAP->mp_NextTimer;

				timerConfig.m_Time=timerConfig.mp_TimerInfo->m_Time; // DEben ser iguales

				if (timerConfig.m_Time > currentTime){

					receiveTimerInfo=0;

					timerConfig.mp_TimerInfo->m_State=edroomTimerActive; // Ya esta activo


				} else {

					timerConfig.mp_TimerInfo->m_State=edroomTimerSent;


					pComponent->m_Mutex.Wait();

               #ifdef _EDROOM_NO_INHERIT_MSG

		      	pComponent->m_ComponentTask.SetMaxPrioMsg( timerConfig.mp_TimerInfo->mp_Msg->priority);
      			#else

		      	pComponent->PrioInheritanceInSendMsg(timerConfig.mp_TimerInfo->mp_Msg->priority);
		#endif

		#ifdef _EDROOM_SYSTEM_CLOSE

					if (!pComponent->m_IsFinished)
		#endif
						pComponent->m_MsgQueue.In(timerConfig.mp_TimerInfo->mp_Msg);

					pComponent->m_Mutex.Signal();

				//Next Timer
					ptimerSAP->mp_NextTimer=timerConfig.mp_TimerInfo->mp_Next;


				}

			}

#ifdef _EDROOM_SYSTEM_CLOSE
		}
#endif

     //SUPRIMIDO, SIEMPRE A URGENTE
 	  //	if(receiveTimerInfo)
			// Pongo la prioridad de la tarea al minimo si no tiene TimerInfo
 	  //		ptimerSAP->mp_TimerTask->SetPriority(EDROOMprioMINIMUM);

     	ptimerSAP->m_Mutex.Signal();                             // libera la exclusin mutua.


#ifdef _EDROOM_SYSTEM_CLOSE

	}while(!isTimerSAPFinished);


	ptimerSAP->m_WaitComponentSem.Signal();

#else

	}while(1);

#endif


}

//**********************************************************************
//**************** FUNCIONES MIEMBRO PUBLICAS **************************

//**********************************************************************
//funcion miembro       InformAt


CEDROOMTimer       CEDROOMTimingSAP::InformAt(CEDROOMTimingInterface* interf
									, Pr_Time timeValue, TEDROOMPriority MsgPrio
									, void *data, CEDROOMPool * bloqueMemData){

	 TEDROOMUInt32 indice;
	 CEDROOMTimerInfo *pTimerInfo;
	 CEDROOMTimeOutMessage *pTimeOutMsg;
	 CEDROOMTimer TimerId;
	 //TEDROOMPriority prioComponent;
	 //TEDROOMPriority maxPrio;



//Prueba

#ifdef _EDROOM_IS_DEBUG_

	 if (interf->m_IsRegistered){ 	// Indica si el puerto esta registrado o no.


#endif


		//Mutex

		mp_Component->m_Mutex.Wait();
		//Hago que el Component tome momentaneamente la prioridad del mensaje si esta
		//es menor (mas prioritario)

		mp_Component->mp_ComponentTask->SetMaxPrioTmp(MsgPrio);
    	//Reservo el mensaje de TimeOut
      	pTimeOutMsg=mp_TimeOutMsgPool->AllocData();

		//FinMutex
		mp_Component->m_Mutex.Signal();

		//Saca del bloque un nuevo elemento para guardar el estado del
		// timer

		m_Mutex.Wait();  //Mutex del servicio del Temp
		pTimerInfo=mp_TimerInfoPool->AllocData(indice);


		// Si el indice es EDROOMUINT32_MAX ya estan utilizados todos los timers disponibles
		// y el Timer no sera reservado

#ifdef _EDROOM_IS_DEBUG_

		if (indice ==EDROOMUINT32_MAX){
			mp_TimerInfoPool->FreeData(pTimerInfo);
         mp_TimeOutMsgPool->FreeData(pTimeOutMsg);
			//Libero Mutex
			m_Mutex.Signal();
		}

		else{

#endif

			//Libero Mutex
			m_Mutex.Signal();

			Pr_Time currentTime;

			currentTime.GetTime();


			// ******COMPLETO TimerInfo

			// El timer va a estar en principio activo
			pTimerInfo->m_State=edroomTimerActive;

			// El tiempo en el que esta programado es timeValue
			pTimerInfo->m_Time=timeValue;

			// identificado por el propio indice que es lo que se devuelve

			pTimerInfo->m_Index=indice;

			// Tambien se identifica con el tiempo de programacion del timer
			pTimerInfo->m_TimeStamp=currentTime;


			// *******COMPLETO TimerId

			// Completo el identificador del Timer con el tiempo actual
			// El indice se completa al final

			TimerId.m_TimeStamp=currentTime;

			// Que el identificador del Timer apunte al bloque con la informacion
			// sobre el timer

			TimerId.mp_TimerInfo=pTimerInfo;


			// *******COMPLETO TimerOutMsg

			// Relleno sus campos

			pTimeOutMsg->signal=0; // Timeout tiene como valor un 0

			pTimeOutMsg->Time=timeValue;     //Tiempo en el que se envia el mp_Msg

			pTimeOutMsg->priority=MsgPrio;

			pTimeOutMsg->data=data;

			pTimeOutMsg->mp_MsgPool=mp_TimeOutMsgPool;

			pTimeOutMsg->mp_DataPool=bloqueMemData;  // Es NULL si no se proporciona

			pTimeOutMsg->mp_Interface=interf;

			pTimeOutMsg->mp_TimerInfo=pTimerInfo;   // apuntador al estado
															//del timer.

			pTimeOutMsg->mp_TimerInfoPool=mp_TimerInfoPool; //apuntador al bloque
													// que reserva el estado del timer

			pTimeOutMsg->mp_Mutex=&m_Mutex;   // apuntador al Semaforo


			// *******COMPLETO TimerInfo 2

			pTimerInfo->mp_Msg=pTimeOutMsg;


			// *******CAPTURO MUTEX

			m_Mutex.Wait();

			if(mp_NextTimer){

				//SUPRIMIDO, EN ESTE CASO SIEMPRE ESTA EN URGENTE // Ajusto prioridad de la tarea
								//mp_TimerTask->SetPriority(maxPrio);


				// Si el timer esta Activo y tiene mayor tiempo que el nuevo, posponerlo
				// pasadolo otra vez a Ready y dejar este en Active


				if ((mp_NextTimer->m_State==edroomTimerActive)&& (mp_NextTimer->m_Time >timeValue)){

						mp_NextTimer->m_State= edroomTimerReady;

						// **** INSERTA EL PRIMERO EN LA COLA

						pTimerInfo->mp_Next=mp_NextTimer;
						mp_NextTimer=pTimerInfo;

						// *******LIBERO MUTEX

						// *******SIGNAL DEL SEMWAITTIMED PARA QUE SE PROGRAME EL SIGUIENTE

						m_SynchrSem.Signal();

						m_Mutex.Signal();



				}else {

						bool found;

						found=false;


						// *******YA NO ESTA ACTIVO SOLO LISTO

						pTimerInfo->m_State=edroomTimerReady;


						CEDROOMTimerInfo *aux;
						aux=mp_NextTimer;

						// **** INSERTA EN LA COLA, NUNCA EL PRIMERO

						while(aux->mp_Next&&!found){

							if (aux->mp_Next->m_Time<timeValue){

								aux=aux->mp_Next;

								//SUPRIMIDO, SIEMPRE EN URGENTE// Va actualizando la prioridad de los timers si es menor (mayor en valor)

								//if(aux->mp_Msg->priority > MsgPrio)
									//aux->mp_Msg->priority=MsgPrio;

							}
							else
								found=true;

						}
						pTimerInfo->mp_Next=aux->mp_Next;
						aux->mp_Next=pTimerInfo;

						// *******LIBERO MUTEX

						m_Mutex.Signal();

				}


			}else {


					// NO HAY NINGUNO EN LA COLA


					CEDROOMTimerConfig timerConfig;


					mp_NextTimer=pTimerInfo;
					pTimerInfo->mp_Next=NULL;

					// SUPRIMIDO SIEMPRE a URGENTE
					//mp_TimerTask->SetMaxPrioMsg(EDROOMprioURGENT);

					// *******COMPLETO TimerConfig

					//Configuracion del timer

					timerConfig.m_Time=timeValue; // Tiempo en el que se programa el timeout

					timerConfig.mp_TimerInfo=pTimerInfo;

					// *******LIBERO MUTEX

					m_Mutex.Signal();


               		//Hago que el Component tome momentaneamente la prioridad URGENTE para conseguir el retorno
					//tras la programacin del Timer

					//Mutex
               		mp_Component->m_Mutex.Wait();

      				mp_Component->mp_ComponentTask->SetMaxPrioTmp(EDROOMprioURGENT);

					//FinMutex
					mp_Component->m_Mutex.Signal();

					// *******ENVIO TimerConfig  PORQUE NO HAY NINGUNO

					Pr_Send(m_TimerTask,&timerConfig); // manda el dato al timer

#ifndef _EDROOM_INFORM_AT_NO_NEED_WAIT
					m_WaitComponentSem.Wait();
#endif

			}

#ifdef _EDROOM_IS_DEBUG_
		}

#endif

				//Mutex
		mp_Component->m_Mutex.Wait();

      		//Retorna la prioridad del mensaje
      	mp_Component->mp_ComponentTask->RestorePrioMsg();

				//FinMutex
		mp_Component->m_Mutex.Signal();



#ifdef _EDROOM_IS_DEBUG_
	 // en el caso de haberla cambiado
	 } // fin del ipComponentst
	 else
		indice=EDROOMUINT32_MAX-1; // si no esta repComponentdo devuelve EDROOMUINT32_MAX-1

#endif

	 // Se toma el indice como identificador del timer
	 TimerId.m_Index=indice;

	 return(TimerId);   // devuelve el identificador del timer creado
}

//**********************************************************************




//**********************************************************************


//**********************************************************************
//funcion miembro       cancelTimer



void    CEDROOMTimingSAP::cancelTimer(CEDROOMTimingInterface* interf, 
														CEDROOMTimer &timerId){


	//EDROOM_NO_SWITCH_IN_TIMER_CANCEL
   //mp_Component->m_Mutex.Wait();

      		//Pone a urgente
   //mp_Component->mp_ComponentTask->SetMaxPrioTmp(EDROOMprioURGENT);

				//FinMutex
   //mp_Component->m_Mutex.Signal();


	m_Mutex.Wait(); //Captura mutex

	//Tiene que ser un timer correcto
	if (timerId.m_Index<EDROOMUINT32_MAX-1){ // indice valido

		if (timerId.m_TimeStamp==timerId.mp_TimerInfo->m_TimeStamp){ //con el mismo tiempo

			//***  CANCELAR SI ESTA ENVIADO

			if (timerId.mp_TimerInfo->m_State==edroomTimerSent)
					timerId.mp_TimerInfo->m_State=edroomTimerCancelled;

			//**** CANCELAR Y DESPERTAR SEMAFORO SI ESTA ACTIVO,
			else  if (timerId.mp_TimerInfo->m_State==edroomTimerActive){

					timerId.mp_TimerInfo->m_State=edroomTimerCancelled;
					m_SynchrSem.Signal();

		//EDROOM_NO_SWITCH_IN_TIMER_CANCEL
               //m_WaitComponentSem.Wait();

		  //**** EXTRAER DE LA COLA SI ESTA READY
			}else if (timerId.mp_TimerInfo->m_State==edroomTimerReady){

				// **** NUNCA puede ser EL PRIMERO

				CEDROOMTimerInfo *aux,*foundTimer;
				bool found;

				found=false;
				aux=mp_NextTimer;

				while(aux->mp_Next&&!found){

					if (aux->mp_Next->m_Index==timerId.m_Index&&aux->mp_Next->m_TimeStamp==timerId.m_TimeStamp){

						found=true;

						foundTimer=aux->mp_Next;

						aux->mp_Next=foundTimer->mp_Next;

						mp_Component->m_Mutex.Wait();

						CEDROOMMessage * auxMsg=(CEDROOMMessage *)foundTimer->mp_Msg;

						EDROOMFreeMessage(auxMsg);


						foundTimer->mp_Msg=NULL;

						mp_Component->m_Mutex.Signal();

						mp_TimerInfoPool->FreeData(foundTimer);


					}
					else	aux=aux->mp_Next;

				}

			}

		  //**** SI ESTA EN OTRO ESTADO, NADA


		}
}


	timerId.m_Index=EDROOMUINT32_MAX;

	m_Mutex.Signal();  // libera la exclusin mutua.


   //EDROOM_NO_SWITCH_IN_TIMER_CANCEL

   				//Mutex
   //mp_Component->m_Mutex.Wait();

      		//Retorna la prioridad del mensaje
   //mp_Component->mp_ComponentTask->RestorePrioMsg();

				//FinMutex
   //mp_Component->m_Mutex.Signal();


}


void CEDROOMTimingSAP::Start(){


	CEDROOMTimingSAP * pTimingSAP;

	pTimingSAP=this;
	Pr_Send(m_TimerTask,&pTimingSAP); // manda el dato apComponentr

}





//**********************************************************************
//       CEDROOMTimmingMemory SetMemory


void CEDROOMTimingMemory::SetMemory(TEDROOMUInt32   elemNumber
									, CEDROOMTimerInfo * pTimerInfoMem_
									, TEDROOMBool *pTimerInfoMemMarks
									, CEDROOMTimeOutMessage* pTimeOutMessageMem
									, TEDROOMBool *pTimeOutMessageMemMarks)

	  {


		m_TimeOutMessMem.SetMemory(elemNumber, pTimeOutMessageMem, pTimeOutMessageMemMarks);

		m_TimerInfoMem.SetMemory(elemNumber, pTimerInfoMem_, pTimerInfoMemMarks);

	  }


//**********************************************************************
//       CEDROOMTimerInfo SetMemory



void CEDROOMTimerInfoPool::SetMemory(TEDROOMUInt32 elemNumber
								,CEDROOMTimerInfo* PDataPool
								,TEDROOMBool * pPoolMarks ){


	CEDROOMMemoryPool::SetMemory(elemNumber,PDataPool, pPoolMarks, sizeof (CEDROOMTimerInfo));

}


CEDROOMTimerInfo * CEDROOMTimerInfoPool::AllocData(TEDROOMUInt32 &ind){

				return (CEDROOMTimerInfo * )CEDROOMMemoryPool::AllocData(ind);
}





/*!
 * \brief edroomqueue cpp (edroom services library) 
 * 
 * \author Oscar Rodrguez Polo
 * \date $Date: 2010-03-04 09:08:17 $
 * \Version $Revision: 1.1.4.5 $
 * 
 * $Log: edroomqueue.cpp,v $
 * Revision 1.1.4.5  2010-03-04 09:08:17  opolo
 * Changed the names of the attributes
 *
 * Revision 1.1.4.4  2010-02-15 10:09:17  opolo
 * actualizados los nombres de los archivos y servicios
 *
 * Revision 1.1.4.3  2006/11/09 15:23:12  opolo
 * Use the new name of the classes that manage the pools
 * 	EDROOMPool EDROOMMemoryPool and EDROOMProtectedMemoryPool
 *
 * Revision 1.1.4.2  2006/10/18 18:31:51  opolo
 * Add Log
 *
 *
 * Revision 1.1.4.1  2006/10/18 18:07:20  opolo
 * *** empty log message ***
 * 
 */


//***************************************************************************
// CEDROOMQueue::CQueueNode


	CEDROOMQueue::CQueueNode::CQueueNode(){
		mp_Msg=NULL;
		mp_Next=NULL;
	}

//***************************************************************************
// CEDROOMQueue::CQueueHead

	CEDROOMQueue::CQueueHead::CQueueHead(){
		mp_First=NULL;
		mp_Last=NULL;
		mp_Next=NULL;
	}




//***************************************************************************
// CEDROOMQueue

// ****************************************************************************
///////////////DEFINICION DEL CONSTRUCTOR ////////////////////////////////////
// ****************************************************************************

// Revisada y comentada
// PROBADA

#ifndef _EDROOM_IS_DEBUG_

CEDROOMQueue::CEDROOMQueue(unsigned Max_Num_Mess,
					Pr_Task * pTask,
					Pr_SemaphoreRec * pMutexSem,
					unsigned prioNumber,
					CEDROOMQueueNodesPool * pNodesPool,
					CQueueHead * pQueueHeads
					)
					:m_NewMsgSem(0)

#else

CEDROOMQueue::CEDROOMQueue(unsigned Max_Num_Mess,
					Pr_Task * pTask,
					Pr_SemaphoreRec * pMutexSem,
					unsigned prioNumber,
					CEDROOMQueueNodesPool * pNodesPool,
					CQueueHead * pQueueHeads,
					const char * pQueueName 
					)
					:m_NewMsgSem("Sem_Nuev_Mens",0), mp_QueueName(pQueueName)
					
#endif


{

	m_MaxNumMsg= Max_Num_Mess;

	m_IsBlocked=0;
	m_MsgCounter=0;
	m_PrioNumber=prioNumber;

	mp_Task = pTask;
	mp_MutexSem = pMutexSem;

	mp_NodesPool=pNodesPool;
	mp_QueueHeads=pQueueHeads;


	for(unsigned int i=0; i<m_PrioNumber; i++)
		mp_QueueHeads[i].m_Priority=(TEDROOMPriority)i;


	mp_FirstQueueHead=NULL;

}

// ****************************************************************************
///////////////DEFINICION DEL DESTRUCTOR ////////////////////////////////////
// ****************************************************************************

// Revisada y comentada
// PROBADA

#ifdef _EDROOM_SYSTEM_CLOSE

CEDROOMQueue::~CEDROOMQueue()
{

}


// ****************************************************************************
///////////////DEFINICION DE FREEMEM ////////////////////////////////////
// ****************************************************************************

// Revisada y comentada
// PROBADA

void CEDROOMQueue::FreeMem()
{
	CQueueNode * aux1_nodo,* aux2_nodo;
	CQueueHead *aux1_cabeza;


	//La cabeza de la cola auxiliar esta apuntada por mp_FirstQueueHead
	aux1_cabeza=mp_FirstQueueHead;

	while(aux1_cabeza)       //Recorro las colas liberando la memoria de los
	{                        //nodos y de las cabezas
				 //Incluyendo las de los mensajes que guardan

		aux1_nodo=aux1_cabeza->mp_First;
		while(aux1_nodo)
		{
			EDROOMFreeMessage(aux1_nodo->mp_Msg); //Libera la memoria
							 //del mensaje
			aux2_nodo=aux1_nodo;
			aux1_nodo=aux1_nodo->mp_Next;
			mp_NodesPool->FreeData(aux2_nodo);
		}
		aux1_cabeza=aux1_cabeza->mp_Next;
	}

									//Recorro la cola de diferidos liberando la memoria
									 //de los nodos


}

#endif


// ****************************************************************************
/////////////////DEFINICION FUNCIONES MIEMBRO PUBLICAS///////////////////////
// ****************************************************************************

// ****************************************************************************
///////////////FUNCION MIEMBRO   LLena ////////////////////////////////////
// ****************************************************************************
	TEDROOMBool CEDROOMQueue::IsFull(){

		 return (TEDROOMBool)(m_MsgCounter==m_MaxNumMsg);
	}
// ****************************************************************************
///////////////FUNCION MIEMBRO   In ////////////////////////////////////
// ****************************************************************************

// Mete un mensaje en la cola de prioridad correspondiente

// Revisada y comentada
// PROBADA

#ifdef _EDROOM_IS_DEBUG_

TEDROOMInt8 CEDROOMQueue::In (CEDROOMMessage * pMsg){

		TEDROOMInt8 error;


#else

void CEDROOMQueue::In (CEDROOMMessage * pMsg){

#endif



		TEDROOMPriority priority=pMsg->priority;


#ifdef _EDROOM_IS_DEBUG_

		if (pMsg==NULL)              // No hay mensaje. ERROR
			error = 1;

		else	{

#endif

			CQueueNode *p_new_node; // Apuntador auxiliar para manejar el nuevo nodo

			//m_Mutex.Wait();                        // Captura la excluxin mutua de la cola.

#ifdef _EDROOM_IS_DEBUG_

			if (m_MsgCounter==m_MaxNumMsg){

				// Si la cola est llena falla.

				error=1;

                EDROOMFError << mp_QueueName << " Queue FULL" ;
		        EDROOMFError.close();
		        //exit(1);

				}
			else {
				error=0;  // No ha habido fallos.

#endif
				p_new_node=mp_NodesPool->AllocData(); // Nuevo nodo
				p_new_node->mp_Msg=pMsg;
				p_new_node->mp_Next=NULL;

				m_MsgCounter++;

				//Aadir en la cola correspondiente a esa prioridad

				if(PutInNode(mp_QueueHeads + priority,p_new_node))
					// Si la cola estaba empty hay que actualizar la cola auxiliar
					UpDateSortedQueueHeadsList(priority);



				// Si el receptor est bloqueado esperando un mensaje y no ha fallado este
				// envio, despierta al receptor.



				if (m_IsBlocked){

					m_IsBlocked=0; // Ya est desbloqueada.
					m_NewMsgSem.Signal();

				}


#ifdef _EDROOM_IS_DEBUG_

			}

		// Devuelve si ha fallado el intento de meter el mensaje en la cola.
		}

		return(error);

#endif



}


// ****************************************************************************
///////////////FUNCION MIEMBRO   Out ////////////////////////////////////
// ****************************************************************************

// Saca un mensaje de la cola     // Espera hasta que haya un menjaje en la cola

// Revisada y comentada
// PROBADA

#ifdef _EDROOM_IS_DEBUG_

	TEDROOMInt8 CEDROOMQueue::Out(CEDROOMMessage * &p_Msg){

#else

	TEDROOMBool CEDROOMQueue::Out(CEDROOMMessage * &p_Msg){

#endif
	 CQueueNode *p_node; // apuntador auxiliar

	 TEDROOMPriority priority;  // Prioridad del mensaje

	 // Captura la exclusin mutua de la cola
	 mp_MutexSem->Wait();

	 // Hay mensajes en la cola

	 if(!mp_FirstQueueHead){


			m_IsBlocked++;  // Hay una tarea mas bloqueada esperando.

			// Libera la Exclusin mutua de la cola

			mp_MutexSem->Signal();

			// Espera el nuevo mensaje.
			m_NewMsgSem.Wait();

			// HA LLEGADO EL NUEVO MENSAJE.

			// Captura la exclusin mutua de la cola

			mp_MutexSem->Wait();


	 }


	 // AQUI SEGURO QUE HAY MENSAJE

	// Saca de la cola de mayor prioridad.
	 TakeOutNode(p_node,priority);

	 mp_Task->SetPriority(priority); // Actualizo la prioridad del destino.


	 m_MsgCounter--;


	 p_Msg=p_node->mp_Msg;

		// Devuelvo la memoria del nodo

	 void * aux_void_p_node= p_node;

	 mp_NodesPool->FreeData(aux_void_p_node);

	 p_node=NULL;

		// Libera la exclusin mutua.

	 mp_MutexSem->Signal();

#ifdef _EDROOM_IS_DEBUG_

	 return(0);

#else

	return(false);
#endif

}


void CEDROOMQueue::UpDateSortedQueueHeadsList(TEDROOMPriority priority){

 CQueueHead *aux,*previous,*newHead;

 newHead=mp_QueueHeads+priority;

 TEDROOMBool newHeadManaged=false;

 if(!mp_FirstQueueHead){

		mp_FirstQueueHead=newHead;
		mp_FirstQueueHead->mp_Next=NULL;


 }else if (mp_FirstQueueHead->m_Priority > priority){

			aux=mp_FirstQueueHead;
			mp_FirstQueueHead=newHead;
			mp_FirstQueueHead->mp_Next=aux;

 }else {
			aux=mp_FirstQueueHead;

			while((!newHeadManaged)){

				if  (!aux->mp_Next){   // No hay siguiente cola

					 aux->mp_Next= newHead;
					 newHead->mp_Next=NULL;    // No hay siguiente
					 newHeadManaged=1;

				} else {

						previous=aux;
						aux=aux->mp_Next;

						if (aux->m_Priority > priority) {// Hay mas cabezas pero de prioridad
														 // menor (mayor numero)

							 newHead->mp_Next=aux;  // La mete en la lista de cabezas de colas
							 previous->mp_Next=newHead;
							 newHeadManaged=1;
						}
				}
			}

 }

}


// ****************************************************************************
///////////////FUNCION MIEMBRO  GetMaxPriority  ////////////////////////////////////
// ****************************************************************************
// Funcion que devuelve la prioridad del menseje que esta primero en la cola

void  CEDROOMQueue::SetToMsgPriority(void){

  TEDROOMPriority priority;



  if (mp_FirstQueueHead)

		priority=mp_FirstQueueHead->m_Priority;

  else

		priority=EDROOMprioMINIMUM; //Minima prioridad puesto que no


  mp_Task->SetPriority(priority); // Actualizo la prioridad del destino.


}




// ****************************************************************************

/////////////////DEFINICION FUNCIONES MIEMBRO PRIVADAS///////////////////////

// ****************************************************************************



// ****************************************************************************
///////////////FUNCION MIEMBRO   Meter_en_cola  //////////////////////////////
// ****************************************************************************

// Revisada y comentada
// PROBADA

TEDROOMBool  CEDROOMQueue::PutInNode(CQueueHead *head, CQueueNode *p_node)
{
	TEDROOMBool empty=true;

	if (head->mp_First)  // no esta empty la cola
		{
		head->mp_Last->mp_Next=p_node;  // lo mete al final de la cola
		head->mp_Last=p_node;
		empty=0;
		}
	 else  // Esta empty.
		{
		head->mp_First=p_node;

		head->mp_Last=head->mp_First;  // UNICO ELEMENTO

		}
	 return empty;

}


// ****************************************************************************
///////////////FUNCION MIEMBRO   Sacar de colas  //////////////////////////////
// ****************************************************************************


// Saca un nodo de una lista de colas sabiendo que hay por lo menos un nodo
// en alguna cola. POR ESO NO SE CHEQUEA SI NO HA ENCONTRADO NINGUN NODO.

// Revisada y comentada
// PROBADA

void CEDROOMQueue::TakeOutNode(CQueueNode * &p_node, TEDROOMPriority &priority) //Saco de colas no urgentes

{

  //Tomo el primero de la cola de mas prioridad
  p_node=mp_FirstQueueHead->mp_First;

  priority=mp_FirstQueueHead->m_Priority;

  //Actualizo el puntero al primero de la cola de esa prioridad
  mp_FirstQueueHead->mp_First=p_node->mp_Next;

  //Si la cola esta empty paso a la siguiente

  if(!mp_FirstQueueHead->mp_First)

	mp_FirstQueueHead=mp_FirstQueueHead->mp_Next;

}

TEDROOMPriority CEDROOMQueue::GetMaxQueuedMsgPriority(void)
{
	TEDROOMPriority priority = EDROOMprioIDLE;

	if (mp_FirstQueueHead)
	{
		priority = mp_FirstQueueHead->m_Priority;
	}

	return priority;
}
   
void CEDROOMQueue::CEDROOMQueueNodesPool::SetMemory(TEDROOMUInt32 elemNumber, CQueueNode * pPoolData
								,TEDROOMBool * pPoolMarks){

   CEDROOMMemoryPool::SetMemory(elemNumber,pPoolData, pPoolMarks, sizeof (CEDROOMQueue::CQueueNode));

}
 	 

CEDROOMQueue::CQueueNode * CEDROOMQueue::CEDROOMQueueNodesPool::AllocData(){

				return (CEDROOMQueue::CQueueNode * )CEDROOMMemoryPool::AllocData();
}



/*!
 * \brief edroomcomm cpp (edroom services library) 
 * 
 * \author Oscar Rodrguez Polo
 * \date $Date: 2010-03-04 09:08:17 $
 * \Version $Revision: 1.1.4.5 $
 *
 * $Log: edroomcomm.cpp,v $
 * Revision 1.1.4.5  2010-03-04 09:08:17  opolo
 * Changed the names of the attributes
 *
 * Revision 1.1.4.4  2010-02-15 10:09:17  opolo
 * actualizados los nombres de los archivos y servicios
 *
 * Revision 1.1.4.3  2006/11/09 15:23:12  opolo
 * Use the new name of the classes that manage the pools
 * 	CEDROOMPool EDROOMMemoryPool and EDROOMProtectedMemoryPool
 *
 * Revision 1.1.4.2  2006/10/18 18:31:51  opolo
 * Add Log
 *
 *
 * Revision 1.1.4.1  2006/10/18 18:07:20  opolo
 * *** empty log message ***
 * 
 */


		
//***************************************************************************
//								FUNCIONES MIEMBRO DE CEDROOMLocalTXChannel


//Constructor

CEDROOMLocalTXChannel::CEDROOMLocalTXChannel(){

		mp_SenderPort=NULL;    //Los dos puertos que forman la conexion
		mp_ReceiverPort=NULL;

		mp_ReceiverMsgPool=NULL;

			// Reservo memoria para sus mensajes sincronos
			// Solo reservo memoria para tres mensajes sincronos
			// que son los que pueden ser solicitados simultaneamente.
}



// asynchronous communication primitives:

void CEDROOMLocalTXChannel::send (TEDROOMSignal signal, TEDROOMPriority priority
									, void *p_data, CEDROOMPool * p_DataPool){

	CEDROOMMessage *p_Msg;
  
#ifdef _EDROOM_IS_DEBUG_


	TEDROOMCommError error=EDROOMNoErrorComm;

//	if(p_QueueReceiver->Full()&& (priority!=EDROOMprioURGENT)){
  	if(mp_ReceiverQueue->IsFull()){

		error= EDROOMFullQueueMens;
		if (p_data)
			p_DataPool->FreeData(p_data);

	}else if ((*mp_SenderToReceiverSignalTranslator)(signal)== EDROOMNoSignal){

		error= EDROOMSignalInvalidate;
		if (p_data)
			p_DataPool->FreeData(p_data);

	}

	else	{  // No hay error

#endif



		// Si la prioridad del mensaje que se enva es mayor que la actual de la tarea emisora,
		//se modifica de forma temporal igualndose a la del mensaje enviado;

		mp_SenderPort->mp_Component->m_Mutex.Wait();
		mp_SenderTask->SetMaxPrioTmp(priority);
		mp_SenderPort->mp_Component->m_Mutex.Signal();

#ifdef _EDROOM_IS_DEBUG_

		// Si el pool de mensajes esta vacio la comunicacion se establece, pero el
		// metodo devuelve como error EDROOMEmptyPoolMens

		if (mp_ReceiverMsgPool->IsEmpty())
			error=EDROOMEmptyPoolMens;


#endif

		// Reservar memoria para el mensaje
		mp_ReceiverPort->mp_Component->m_Mutex.Wait();

#ifdef _EDROOM_NO_INHERIT_MSG
		p_receiverTask->SetMaxPrioMsg( priority);
#else
		mp_ReceiverPort->mp_Component->PrioInheritanceInSendMsg(priority);
#endif

		p_Msg=mp_ReceiverMsgPool->AllocData();
		mp_ReceiverPort->mp_Component->m_Mutex.Signal();

		// Rellenar sus campos;

		// Seal

		p_Msg->signal=(*mp_SenderToReceiverSignalTranslator)(signal);

		//apuntador al manejador de memoria de los Mensajes del Receptor

		p_Msg->mp_MsgPool=mp_ReceiverMsgPool;

		//dato enviado
		p_Msg->data=p_data;

		//manejador de memoria
		p_Msg->mp_DataPool=p_DataPool;

		//Prioridad del mensaje

		p_Msg->priority=priority;

		//Completo el campo interf para que apunte al puerto por el que se recibe
		// el mensaje
		p_Msg->mp_Interface=mp_ReceiverPort;

		// Se mete el mensaje en la cola asociada a este puerto.

		mp_ReceiverPort->mp_Component->m_Mutex.Wait();
		mp_ReceiverQueue->In(p_Msg);
		mp_ReceiverPort->mp_Component->m_Mutex.Signal();


		// Se restarura la prioridad del mensaje de la tarea emisora

#ifdef _EDROOM_INTERNAL_EVENT_RESTORE_PRIO
		mp_SenderPort->mp_Component->m_Mutex.Wait();
		mp_SenderTask->RestorePrioMsg();
		mp_SenderPort->mp_Component->m_Mutex.Signal();
#endif

#ifdef _EDROOM_IS_DEBUG_

	}

    if (error!=EDROOMNoErrorComm){
		EDROOMFError 	<< mp_SenderPort->mp_Component->EDROOMName << "/" 
						<< mp_SenderPort->EDROOMName << " .send : " 
						<< EDROOMErrorCommNames[error];
		EDROOMFError.close();
		//exit(1);
    }

#endif

	//return error;


}





CEDROOMMessage * CEDROOMLocalTXChannel::invoke(TEDROOMSignal signal, TEDROOMPriority priority, void *p_data, CEDROOMPool * p_DataPool){

	CEDROOMSynchrMessage *p_Msg;

	Pr_SemaphoreBin *apSemSincr;


#ifdef _EDROOM_IS_DEBUG_

	TEDROOMCommError error;

    error=EDROOMNoErrorComm;

	// Ver si hay errores
	// Si hay errores el mensaje no se manda

	if ((*mp_SenderToReceiverSignalTranslator)(signal)== EDROOMNoSignal){

		error= EDROOMSignalInvalidate;

	}

	else	{  // No hay error


#endif

            // La prioridad del emisor
            //se modifica de forma temporal a URGENTE

        //Free Mutex    
		mp_SenderPort->mp_Component->m_Mutex.Wait();

#ifndef _EDROOM_NO_INHERIT_MSG
        TEDROOMPriority maxprio;
            //if the priority of the message is different update
        mp_SenderTask->SetMaxPrioTmp(priority);
            //Get the priority of the sender task
        maxprio=mp_SenderTask->GetTaskPrio();
            // the block of the sender
        mp_SenderPort->mp_Component->mp_ComponentIsLockingMe=
        							mp_ReceiverPort->mp_Component;
#endif


#ifdef _EDROOM_URGENT_INVOKE

		p_senderTask->SetMaxPrioTmp(EDROOMprioURGENT);

#endif

        //Free Mutex
		mp_SenderPort->mp_Component->m_Mutex.Signal();



#ifndef _EDROOM_NO_INHERIT_MSG

            //the receptor inherit maxprio

#ifdef _EDROOM_IS_DEBUG_

        mp_ReceiverPort->mp_Component->m_Mutex.Wait();

        if(mp_ReceiverPort->mp_Component->PrioInheritanceInInvokeMsg(mp_SenderPort->mp_Component,maxprio))
            error=EDROOMInterblock;

        mp_ReceiverPort->mp_Component->m_Mutex.Signal();

        if(error==EDROOMNoErrorComm){

#else
            mp_ReceiverPort->mp_Component->m_Mutex.Wait();
            mp_ReceiverPort->mp_Component->PrioInheritanceInInvokeMsg(mp_SenderPort->mp_Component,maxprio);
            mp_ReceiverPort->mp_Component->m_Mutex.Signal();

#endif  // _EDROOM_IS_DEBUG_


#else
		//Pone al receptor a la prioridad del mensaje para evitar la inversion de prioridad
		mp_ReceiverPort->mp_Component->m_Mutex.Wait();
		p_receiverTask->SetMaxPrioMsg(priority);
		mp_ReceiverPort->mp_Component->m_Mutex.Signal();

#endif 

		// Espera a que haya memoria para el mensaje

		// Tiene su propio semaforo de exclusion mutua y la comunicacion se
		// realiza con prioridad URGENTE por lo que no hace falta que sea un
		// semaforo de recurso

		p_Msg=mp_SynchrMsgPool->AllocData();

		// Rellenar sus campos;

		// Seal

		p_Msg->signal=(*mp_SenderToReceiverSignalTranslator)(signal);

		//apuntador al pool de memoria de los Mensajes sincronos

		p_Msg->mp_MsgPool=mp_SynchrMsgPool;

		// dato
		p_Msg->data=p_data;

		// manejador de memoria del dato

		p_Msg->mp_DataPool=p_DataPool;

		//Prioridad del mensaje

          //The msg inherit

#ifdef _EDROOM_NO_INHERIT_MSG

		p_Msg->priority=priority;

#else

		    p_Msg->priority=maxprio;  //The msg inherits the priority too.

#endif

		//Completo el campo interf para que apunte al puerto por el que se recibe
		// el mensaje

		    p_Msg->mp_Interface=mp_ReceiverPort;

		// Si el pool de mensajes esta vacio la comunicacion se establece, pero el
		// metodo devuelve como error EDROOMEmptyPoolMens

#ifdef _EDROOM_IS_DEBUG_

		if ((*mpp_MsgBack)!=NULL){
			  error=EDROOMMsgBackUsed;

		}

#endif

		//Semaforo para la sincronizacion

		apSemSincr=&(p_Msg->m_SynchrSem);

		// Coloco el apuntador a ese mensaje de retorno en uno de los campos
		// del mensaje que envio

		p_Msg->mp_MsgBack=mp_MessageBack;

		// Indico al receptor que el emisor esta esperando
		p_Msg->m_IsSenderWaiting=1;

		// Se mete el mensaje el la cola asociada a este puerto.

		mp_ReceiverPort->mp_Component->m_Mutex.Wait();
		mp_ReceiverQueue->In(p_Msg);
		mp_ReceiverPort->mp_Component->m_Mutex.Signal();

		// Se espera hasta que el receptor haga un reply y seale
		// el semaforo en el que va el mensaje.

		apSemSincr->Wait();

		// Se restaura la prioridad antigua si se habia modificado

		mp_SenderPort->mp_Component->m_Mutex.Wait();

#ifndef _EDROOM_NO_INHERIT_MSG
            mp_SenderPort->mp_Component->mp_ComponentIsLockingMe=NULL;
#endif
		mp_SenderTask->RestorePrioMsg();
		mp_SenderPort->mp_Component->m_Mutex.Signal();

		// Se retorna el apuntador al mensaje de retorno

#ifndef _EDROOM_NO_INHERIT_MSG
#ifdef _EDROOM_IS_DEBUG_
	}
#endif  //_EDROOM_IS_DEBUG_
#endif //_EDROOM_NO_INHERIT_MSG


#ifdef _EDROOM_IS_DEBUG_
	}

    if (error!=EDROOMNoErrorComm){
		EDROOMFError 	<< mp_SenderPort->mp_Component->EDROOMName << "/" 
						<< mp_SenderPort->EDROOMName << " .invoke : " 
						<< EDROOMErrorCommNames[error];
		EDROOMFError.close();
		//exit(1);
    }

#endif

	return(mp_MessageBack);

}


//***************************************************************************
//								FUNCIONES MIEMBRO DE COOMSAP



//***************************************************************************
// *****************        RegisterInterface *******************************

#ifdef _EDROOM_IS_DEBUG_

TEDROOMInt32 CEDROOMLocalCommSAP::RegisterInterface( TEDROOMInterfaceID id
							, CEDROOMInterface & interf
							, CEDROOMComponent * component
							, const char * InterfaceName){


		interf.EDROOMName=InterfaceName;



#else

TEDROOMInt32 CEDROOMLocalCommSAP::RegisterInterface( TEDROOMInterfaceID id
								, CEDROOMInterface & interf
								, CEDROOMComponent * component){

#endif


		interf.m_IdInterface=id; //Doy un identificador al interface

		interf.mp_Component=component; 			// component propietario del interface

#ifdef _EDROOM_IS_DEBUG_

		// Registro el interfac
		interf.m_IsRegistered=1;

#endif

		// Falta crear la cola de diferidos para el interface

		return(0); //No hay error posible de momento
}

//***************************************************************************
// *****************        DeregisterInterface *******************************




void CEDROOMLocalCommSAP::Connect(CEDROOMInterface &inter1
							,CEDROOMInterface &inter2
							, CEDROOMLocalConnection &connection
							, TEDROOMSignal (f1) (TEDROOMSignal )
							, TEDROOMSignal  (f2) (TEDROOMSignal )){
	
				//Si estan registrados los puertos.

#ifdef _EDROOM_IS_DEBUG_

	if (inter1.m_IsRegistered&&inter2.m_IsRegistered){

#endif

		// Aqui se podia aadir algo sobre la compatibilidad de los protocolos
		//


		connection.m_Channel1.mp_SenderPort=&inter1;     //puertos que la forman

		connection.m_Channel1.mp_ReceiverPort=&inter2;     //puertos que la forman

		connection.m_Channel2.mp_SenderPort=&inter2;     //puertos que la forman

		connection.m_Channel2.mp_ReceiverPort=&inter1;     //puertos que la forman

		// A los puertos se les da tambien el puntero a la conexion

		inter1.mp_Channel=&connection.m_Channel1;
		inter2.mp_Channel=&connection.m_Channel2;

	
		// Apuntador a la tareas propietarias de los puertos

		connection.m_Channel1.mp_SenderTask=inter1.mp_Component->mp_ComponentTask;
		connection.m_Channel1.mp_ReceiverTask=inter2.mp_Component->mp_ComponentTask;
		connection.m_Channel2.mp_SenderTask=inter2.mp_Component->mp_ComponentTask;
		connection.m_Channel2.mp_ReceiverTask=inter1.mp_Component->mp_ComponentTask;

		// Apuntador a la colas de mensajes de los componentes propietarios de los puertos

		connection.m_Channel1.mp_ReceiverQueue=&inter2.mp_Component->m_MsgQueue;
		connection.m_Channel2.mp_ReceiverQueue=&inter1.mp_Component->m_MsgQueue;


		// Apuntador a los manejadores de memoria de los mensajes

		connection.m_Channel1.mp_ReceiverMsgPool=inter2.mp_Component->mp_MsgPool;
		connection.m_Channel2.mp_ReceiverMsgPool=inter1.mp_Component->mp_MsgPool;

		//FUNCIONES DE CONVERSION DE SEALES

		connection.m_Channel1.mp_SenderToReceiverSignalTranslator=f1;
		connection.m_Channel2.mp_SenderToReceiverSignalTranslator=f2;

		// Puntero al MsgBack
		connection.m_Channel1.mpp_MsgBack=&inter1.mp_Component->MsgBack;
		connection.m_Channel1.mp_MessageBack=&inter1.mp_Component->m_MessageBack;


		connection.m_Channel2.mpp_MsgBack=&inter2.mp_Component->MsgBack;
		connection.m_Channel2.mp_MessageBack=&inter2.mp_Component->m_MessageBack;

		connection.m_Channel1.mp_SynchrMsgPool=&inter2.mp_Component->m_SynchrMsgPool;
		connection.m_Channel2.mp_SynchrMsgPool=&inter1.mp_Component->m_SynchrMsgPool;

					//marco los puertos como conectados

#ifdef _EDROOM_IS_DEBUG_

		inter1.m_IsConnected=1;
		inter2.m_IsConnected=1;

	 }

#endif


}



#ifdef _EDROOM_SYSTEM_CLOSE


int CEDROOMLocalCommSAP::DeregisterInterface(CEDROOMInterface & interf){



#ifdef _EDROOM_IS_DEBUG_
		int error=1;

		if (interf.m_IsRegistered){


			interf.m_IsRegistered=0; //Lo desregistro
			error=0;
		  //	delete (interf.apMemMensDi); //borro la memoria que tiene


		}
		return(error); //No hay error posible de momento


#else

		return 0;

#endif

}

#endif




CEDROOMRemoteCommSAP::CEDROOMRemoteCommSAP(TEDROOMUInt32 maxConnections,
		CEDROOMRemoteCommSAPMemory * commSAPMemory) :
		m_RemoteConnectionLocator(commSAPMemory->mp_ItemTableMemory, commSAPMemory->m_ItemTableMemorySize),
		m_MaxConnections(maxConnections)
#ifdef _EDROOM_IS_DEBUG_
		,m_Mutex("Remote Comm SAP Mutex Semaphore")
#endif
{
	mp_MsgPool = &commSAPMemory->m_MessagesPool;
}
/*
void CEDROOMRemoteConnectionPool::SetMemory(TEDROOMUInt32 dimension
							, CEDROOMRemoteConnection * pRemoteConnectionPool
							, TEDROOMBool * pMemoryMarks)
{
	CEDROOMMemoryPool::SetMemory(dimension, pRemoteConnectionPool
			, pMemoryMarks, sizeof (CEDROOMRemoteConnection));
}

CEDROOMRemoteConnection * CEDROOMRemoteConnectionPool::AllocData(void)
{
	return (CEDROOMRemoteConnection * )CEDROOMMemoryPool::AllocData();
}
*/
TEDROOMInt32 CEDROOMRemoteConnectionLocator::Compare(CEDROOMRemoteConnectionLocatorItem * item1
					, CEDROOMRemoteConnectionLocatorItem * item2)
{
    if (item1->m_InterfaceID == item2->m_InterfaceID)
    {
        if (item1->m_ComponentID == item2->m_ComponentID)
            return 0;

        return item1->m_ComponentID > item2->m_ComponentID ? 1 : -1;
    }

    return item1->m_InterfaceID > item2->m_InterfaceID ? 1 : -1;

}

void CEDROOMRemoteConnectionLocator::OrderItems()
{
    unsigned int i, j;

    CEDROOMRemoteConnectionLocatorItem tmp;

    if (mp_ItemTable == NULL)
    {
    	return;
    }

    for (i=1; i < m_numElements; i++)
    {
        tmp = mp_ItemTable[i];

        for (j = i; j > 0 && Compare(mp_ItemTable + j - 1, &tmp) > 0; j--)
        	mp_ItemTable[j] = mp_ItemTable[j-1];

        mp_ItemTable[j] = tmp;
    }
}

CEDROOMRemoteConnectionLocatorItem * CEDROOMRemoteConnectionLocator::SearchForItem(TEDROOMComponentID componentID
										, TEDROOMInterfaceID interfaceID)
{
    int from, to, centre, r;

	if (mp_ItemTable == NULL)
	{
		return NULL;
	}

	from = 0;
	to = m_numElements - 1;

	CEDROOMRemoteConnectionLocatorItem id;
	id.m_ComponentID = componentID;
	id.m_InterfaceID = interfaceID;

    do
    {
    	centre = (from + to) / 2;

        r = Compare (&id, mp_ItemTable + centre);

        if (r == 0)
            return (mp_ItemTable + centre);

        if (r > 0)
        	from = centre + 1;
        else
        	to = centre - 1;
    }
    while (from <= to);

    return NULL;

}

CEDROOMRemoteConnection * CEDROOMRemoteConnectionLocator::SearchFor(TEDROOMComponentID componentID
										, TEDROOMInterfaceID interfaceID)
{
	CEDROOMRemoteConnectionLocatorItem * item = SearchForItem(componentID, interfaceID);
	if (item != NULL)
	{
		return item->mp_RemoteConnection;
	}
	else
	{
		return NULL;
	}
}

TEDROOMInt32 CEDROOMRemoteConnectionLocator::AddItem(TEDROOMComponentID componentID
		, TEDROOMInterfaceID interfaceID
		, CEDROOMRemoteConnection * p_remoteConnection)
{

	if (mp_ItemTable == NULL)
	{
		return -1; // Table empty!
	}

	if (m_numElements + 1 > m_ItemTableSize)
	{
		return -1; // Table full!
	}

	mp_ItemTable[m_numElements].m_ComponentID = componentID;
	mp_ItemTable[m_numElements].m_InterfaceID = interfaceID;
	mp_ItemTable[m_numElements].mp_RemoteConnection = p_remoteConnection;

	m_numElements += 1;

	return 0;
}

TEDROOMInt32 CEDROOMRemoteConnectionLocator::RemoveItem(TEDROOMComponentID componentID
		, TEDROOMInterfaceID interfaceID)
{

	if ((mp_ItemTable == NULL) ||
		(m_ItemTableSize == 0) ||
		(m_numElements == 0))
	{
		return -1; // Table empty!
	}

	CEDROOMRemoteConnectionLocatorItem *  p_Item2Erase = SearchForItem(componentID, interfaceID);

	if (p_Item2Erase == NULL)
	{
		return -1;
	}
	p_Item2Erase->m_ComponentID = EDROOMUINT32_MAX;
	p_Item2Erase->m_InterfaceID = EDROOMUINT32_MAX;
	p_Item2Erase->mp_RemoteConnection = NULL;

	OrderItems();

	m_numElements --;
	return 0;

}



#ifdef _EDROOM_IS_DEBUG_

TEDROOMInt32 CEDROOMRemoteCommSAP::RegisterInterface(TEDROOMInterfaceID id
					, CEDROOMInterface & interface
					, CEDROOMComponent* pComponent
					, const char * interfaceName)
{

	interface.EDROOMName=interfaceName;

#else

TEDROOMInt32 CEDROOMRemoteCommSAP::RegisterInterface( TEDROOMInterfaceID id
					, CEDROOMInterface & interface
					, CEDROOMComponent* pComponent)
{

#endif

	interface.m_IdInterface = id;
	interface.mp_Component = pComponent;

#ifdef _EDROOM_IS_DEBUG_

		// Registro el interfac
		interface.m_IsRegistered=1;

#endif

	return (0);

}

void CEDROOMRemoteCommSAP::Connect(CEDROOMInterface & interface
			, TEDROOMComponentID destinationComponentID
			, TEDROOMInterfaceID destInterfaceID
			, CEDROOMRemoteConnection * remoteConnection
			, CEDROOMRemoteConnectionInfo * pConnectionInfo
			, pFunSerializeData (fGetSerializeFun) (TEDROOMSignal)
			, pFunGetInformation funGetInformation
		    , TEDROOMSignal (senderToNetworkTranslator) (TEDROOMSignal)
		    , TEDROOMSignal (networkToReceiverTranslator) (TEDROOMSignal))
{



	interface.mp_Channel = &remoteConnection->m_TXChannel;

	remoteConnection->m_TXChannel.m_senderInterfaceID = interface.m_IdInterface;
	remoteConnection->m_TXChannel.m_senderGlobalComponentID = interface.mp_Component->m_ComponentID;
	remoteConnection->m_TXChannel.mp_SenderPort = &interface;
	remoteConnection->m_TXChannel.mp_SenderTask = interface.mp_Component->mp_ComponentTask;
	remoteConnection->m_TXChannel.mp_SenderComponent = interface.mp_Component;

    remoteConnection->m_TXChannel.m_destinationGlobalComponentID = destinationComponentID;
    remoteConnection->m_TXChannel.m_destinationInterfaceID = destInterfaceID;

	remoteConnection->m_TXChannel.mp_ConnectionInfo = pConnectionInfo;
	remoteConnection->m_TXChannel.mp_CommSAP = this;
	remoteConnection->m_TXChannel.mp_CommSAPMsgPool = this->mp_MsgPool;
	remoteConnection->m_TXChannel.pGetSerializeFun = fGetSerializeFun;
	remoteConnection->m_TXChannel.SetSenderToReceiveSignalTranslator(senderToNetworkTranslator);

	remoteConnection->m_TXChannel.mp_MessageBack = &interface.mp_Component->m_MessageBack;;

	remoteConnection->m_TXChannel.mp_Connection = remoteConnection;

	remoteConnection->m_RXChannel.mp_ReceiverPort = &interface;
	remoteConnection->m_RXChannel.mp_ReceiverTask = interface.mp_Component->mp_ComponentTask;
	remoteConnection->m_RXChannel.mp_ReceiverQueue = &interface.mp_Component->m_MsgQueue;
	remoteConnection->m_RXChannel.mp_MessageBack = &interface.mp_Component->m_MessageBack;
	remoteConnection->m_RXChannel.mp_NetworkToReceiverSignalTranslator = networkToReceiverTranslator;
	remoteConnection->m_RXChannel.mp_funGetInformation = funGetInformation;

	remoteConnection->m_RXChannel.mp_Connection = remoteConnection;

	// Now we have to add it to the Location Service
	m_RemoteConnectionLocator.AddItem(interface.mp_Component->m_ComponentID, interface.m_IdInterface, remoteConnection);

#ifdef _EDROOM_IS_DEBUG_
	interface.m_IsConnected=1;
#endif

}

CEDROOMRemoteTXChannel::CEDROOMRemoteTXChannel() :
		m_InvokeSem(0)
{

}

void CEDROOMRemoteTXChannel::send (TEDROOMSignal signal,
                                 TEDROOMPriority priority,
                                 void *p_data, CEDROOMPool * p_DataPool)
{
	CEDROOMMessage *p_Msg;

#ifdef _EDROOM_IS_DEBUG_


	TEDROOMCommError error=EDROOMNoErrorComm;

  	if(mp_CommSAP->mp_MsgPool->IsEmpty()){

 		error= EDROOMEmptyPoolMens;
		if (p_data)
			p_DataPool->FreeData(p_data);

	}else if ((*mp_SenderToReceiverSignalTranslator)(signal)== EDROOMNoSignal){

		error= EDROOMSignalInvalidate;
		if (p_data)
			p_DataPool->FreeData(p_data);

	}

	else	{  // No hay error

#endif


		// Si la prioridad del mensaje que se enva es mayor que la actual de la tarea emisora,
		//se modifica de forma temporal igualndose a la del mensaje enviado;

		mp_SenderPort->mp_Component->m_Mutex.Wait();
		mp_SenderTask->SetMaxPrioTmp(priority);
		mp_SenderPort->mp_Component->m_Mutex.Signal();


		// Reservar memoria para el mensaje
		mp_CommSAP->m_Mutex.Wait();
		p_Msg=mp_CommSAPMsgPool->AllocData();
		mp_CommSAP->m_Mutex.Wait();

		// Rellenar el mensaje

		p_Msg->signal=(*mp_SenderToReceiverSignalTranslator)(signal);

		//apuntador al manejador de memoria de los Mensajes del Receptor

		p_Msg->mp_MsgPool=mp_CommSAPMsgPool;

		p_Msg->type = (TEDROOMMessageType)msgTypeSend;

		//dato enviado
		p_Msg->data=p_data;

		//manejador de memoria
		p_Msg->mp_DataPool=p_DataPool;

		//Prioridad del mensaje

		p_Msg->priority=priority;

		//Completo el campo interf para que apunte al puerto por el que se recibe
		// el mensaje
		p_Msg->mp_Interface=mp_SenderPort;

		// Se envia al RemoteCommSAP:

		mp_CommSAP->DeliverMsg(this, p_Msg);

		// Se restaura la prioridad del componente

		mp_SenderPort->mp_Component->m_Mutex.Wait();
		mp_SenderTask->RestorePrioMsg();
		mp_SenderPort->mp_Component->m_Mutex.Signal();



#ifdef _EDROOM_IS_DEBUG_

	}

    if (error!=EDROOMNoErrorComm){
		EDROOMFError 	<< mp_SenderPort->mp_Component->EDROOMName << "/"
						<< mp_SenderPort->EDROOMName << " .send : "
						<< EDROOMErrorCommNames[error];
		EDROOMFError.close();
		//exit(1);
    }

#endif


}

CEDROOMMessage * CEDROOMRemoteTXChannel::invoke(TEDROOMSignal signal, TEDROOMPriority priority
							, void *p_data, CEDROOMPool * p_DataPool)
{

	CEDROOMSynchrMessage *p_Msg;

	Pr_SemaphoreBin *apSemSincr;

#ifdef _EDROOM_IS_DEBUG_

	TEDROOMCommError error;

    error=EDROOMNoErrorComm;

	// Ver si hay errores
	// Si hay errores el mensaje no se manda

	if ((*mp_SenderToReceiverSignalTranslator)(signal)== EDROOMNoSignal){

		error= EDROOMSignalInvalidate;

	}

	else	{  // No hay error


#endif

	// Si la prioridad del mensaje que se enva es mayor que la actual de la tarea emisora,
	//se modifica de forma temporal igualndose a la del mensaje enviado;

	mp_SenderPort->mp_Component->m_Mutex.Wait();

#ifndef _EDROOM_NO_INHERIT_MSG
    TEDROOMPriority maxprio;
    //if the priority of the message is different update
    mp_SenderTask->SetMaxPrioTmp(priority);
    //Get the priority of the sender task
    maxprio=mp_SenderTask->GetTaskPrio();
#endif

#ifdef _EDROOM_URGENT_INVOKE
	mp_senderTask->SetMaxPrioTmp(EDROOMprioURGENT);
#endif

	mp_SenderPort->mp_Component->m_Mutex.Signal();

	p_Msg = &m_SynchrMsg;

	// Rellenar sus campos;

	p_Msg->signal=(*mp_SenderToReceiverSignalTranslator)(signal);

	//apuntador al pool de memoria de los Mensajes sincronos

	p_Msg->mp_MsgPool=NULL;

	// dato
	p_Msg->data=p_data;

	// manejador de memoria del dato

	p_Msg->mp_DataPool=p_DataPool;

	p_Msg->type = (TEDROOMMessageType)msgTypeInvoke;


	//Prioridad del mensaje

      //The msg inherit

#ifdef _EDROOM_NO_INHERIT_MSG
	p_Msg->priority=priority;
#else

    p_Msg->priority=maxprio;  //The msg inherits the priority too.

#endif

	//Completo el campo interf para que apunte al puerto por el que se recibe
	// el mensaje

    p_Msg->mp_Interface=mp_SenderPort;

	//Semaforo para la sincronizacion

    apSemSincr=&(mp_Connection->m_TXChannel.m_InvokeSem);

	// Se envia al RemoteCommSAP:

	mp_CommSAP->DeliverMsg(this, p_Msg);

	// Se espera hasta que el receptor haga un reply y seale
	// el semaforo en el que va el mensaje.

	apSemSincr->Wait();

	// Se restaura la prioridad antigua si se habia modificado

	mp_SenderPort->mp_Component->m_Mutex.Wait();
	mp_SenderTask->RestorePrioMsg();
	mp_SenderPort->mp_Component->m_Mutex.Signal();



#ifdef _EDROOM_IS_DEBUG_
	}

    if (error!=EDROOMNoErrorComm){
		EDROOMFError 	<< mp_SenderPort->mp_Component->EDROOMName << "/"
						<< mp_SenderPort->EDROOMName << " .invoke : "
						<< EDROOMErrorCommNames[error];
		EDROOMFError.close();
		//exit(1);
    }

#endif

	return(mp_MessageBack);


}

void CEDROOMRemoteTXChannel::reply (TEDROOMSignal signal, TEDROOMPriority priority, void *p_Data
		  , CEDROOMPool * p_DataPool)
{


	CEDROOMMessage *p_Msg;

#ifdef _EDROOM_IS_DEBUG_


TEDROOMCommError error=EDROOMNoErrorComm;

	if(mp_CommSAP->mp_MsgPool->IsEmpty()){

		error= EDROOMEmptyPoolMens;
	if (p_Data)
		p_DataPool->FreeData(p_Data);

}else if ((*mp_SenderToReceiverSignalTranslator)(signal)== EDROOMNoSignal){

	error= EDROOMSignalInvalidate;
	if (p_Data)
		p_DataPool->FreeData(p_Data);

}

else	{  // No hay error

#endif


	// Si la prioridad del mensaje que se enva es mayor que la actual de la tarea emisora,
	//se modifica de forma temporal igualndose a la del mensaje enviado;

	mp_SenderPort->mp_Component->m_Mutex.Wait();
	mp_SenderTask->SetMaxPrioTmp(priority);
	mp_SenderPort->mp_Component->m_Mutex.Signal();


	// Reservar memoria para el mensaje
	mp_CommSAP->m_Mutex.Wait();
	p_Msg=mp_CommSAPMsgPool->AllocData();
	mp_CommSAP->m_Mutex.Signal();

	// Rellenar el mensaje

	p_Msg->signal=(*mp_SenderToReceiverSignalTranslator)(signal);

	//apuntador al manejador de memoria de los Mensajes del Receptor

	p_Msg->mp_MsgPool=mp_CommSAPMsgPool;

	p_Msg->type = (TEDROOMMessageType)msgTypeReply;

	//dato enviado
	p_Msg->data=p_Data;

	//manejador de memoria
	p_Msg->mp_DataPool=p_DataPool;

	//Prioridad del mensaje

	p_Msg->priority=priority;

	//Completo el campo interf para que apunte al puerto por el que se recibe
	// el mensaje
	p_Msg->mp_Interface=mp_SenderPort;

	// Se envia al RemoteCommSAP:

	mp_CommSAP->DeliverMsg(this, p_Msg);

	// Se restaura la prioridad del componente

	mp_SenderPort->mp_Component->m_Mutex.Wait();
	mp_SenderTask->RestorePrioMsg();
	mp_SenderPort->mp_Component->m_Mutex.Signal();



#ifdef _EDROOM_IS_DEBUG_

}

if (error!=EDROOMNoErrorComm){
	EDROOMFError 	<< mp_SenderPort->mp_Component->EDROOMName << "/"
					<< mp_SenderPort->EDROOMName << " .send : "
					<< EDROOMErrorCommNames[error];
	EDROOMFError.close();
	//exit(1);
}

#endif

}

CEDROOMRemoteRXChannel::CEDROOMRemoteRXChannel() :
		mp_RemoteSynchrMsgPool(&m_remoteSynchrMsg)
{

}

TEDROOMWord32 CEDROOMRemoteRXChannel::ComponentReceive (TEDROOMSignal signal,
                      TEDROOMMessageType msgType,
                      TEDROOMPriority priority,
                      void * data,
                      TEDROOMWord32 dataSize)
{
    CEDROOMMessage * p_Msg;
    CEDROOMProtectedMemoryPool * p_PoolData;
    pFunDeserializeData pFunDeserialize;

    if (msgType == (TEDROOMMessageType)msgTypeSend)
    {
        // Reservar memoria para el mensaje
    	mp_ReceiverPort->mp_Component->m_Mutex.Wait();

        //p_rxPort->p_actor->SetMaxPrioSendMsg(priority);
    	mp_ReceiverTask->SetMaxPrioMsg(priority);

        p_Msg = mp_ReceiverMsgPool->AllocData();

        mp_ReceiverPort->mp_Component->m_Mutex.Signal();

        p_Msg->signal = (*mp_NetworkToReceiverSignalTranslator)(signal);

        (*mp_funGetInformation)(p_Msg->signal, &pFunDeserialize, &p_PoolData);

        if (pFunDeserialize)
        {
            p_Msg->data = p_PoolData->AllocData();
            p_Msg->mp_DataPool = p_PoolData;
            pFunDeserialize(data, p_Msg->data);
        }
        else
        {
            //dato enviado
            p_Msg->data = NULL;
            p_Msg->mp_DataPool = NULL;
        }

        //apuntador al manejador de memoria de los Mensajes del Receptor

        p_Msg->mp_MsgPool = mp_ReceiverMsgPool;

        //Prioridad del mensaje

        p_Msg->priority = priority;

        //Completo el campo interf para que apunte al puerto por el que se recibe
        // el mensaje
        p_Msg->mp_Interface = mp_ReceiverPort;

        mp_ReceiverPort->mp_Component->m_Mutex.Wait();
        mp_ReceiverQueue->In(p_Msg);
        mp_ReceiverPort->mp_Component->m_Mutex.Signal();
    }
    else if (msgType == (TEDROOMMessageType)msgTypeInvoke)
    {
    	mp_ReceiverPort->mp_Component->m_Mutex.Wait();
    	mp_ReceiverTask->SetMaxPrioMsg(priority);
        p_Msg = mp_RemoteSynchrMsgPool.AllocData();
        mp_ReceiverPort->mp_Component->m_Mutex.Signal();

        p_Msg->signal = (*mp_NetworkToReceiverSignalTranslator)(signal);

        // TODO: Check that p_Msg is != NULL

        (*mp_funGetInformation)(p_Msg->signal, &pFunDeserialize, &p_PoolData);

        if (pFunDeserialize)
        {
            p_Msg->data = p_PoolData->AllocData();
            p_Msg->mp_DataPool = p_PoolData;
            pFunDeserialize(data, p_Msg->data);
        }
        else
        {
            //dato enviado
            p_Msg->data = NULL;
            p_Msg->mp_DataPool = NULL;
        }

        p_Msg->mp_MsgPool=&mp_RemoteSynchrMsgPool;

        p_Msg->priority=priority;

        //Completo el campo interf para que apunte al puerto por el que se recibe
        // el mensaje

        p_Msg->mp_Interface = mp_ReceiverPort;

        // Se mete el mensaje el la cola asociada a este puerto.

        mp_ReceiverPort->mp_Component->m_Mutex.Wait();
        mp_ReceiverQueue->In(p_Msg);
        mp_ReceiverPort->mp_Component->m_Mutex.Signal();

    } else
    {
        mp_MessageBack->signal = (*mp_NetworkToReceiverSignalTranslator)(signal);

        (*mp_funGetInformation)(mp_MessageBack->signal, &pFunDeserialize, &p_PoolData);

        if (pFunDeserialize)
        {
            mp_MessageBack->data = p_PoolData->AllocData();
            mp_MessageBack->mp_DataPool = p_PoolData;
            pFunDeserialize(data, mp_MessageBack->data);
        }
        else
        {
            //dato enviado
            mp_MessageBack->data = NULL;
            mp_MessageBack->mp_DataPool = NULL;
        }
        mp_Connection->m_TXChannel.m_InvokeSem.Signal();
    }
    return (0);
}

CEDROOMRegularRemoteCommSAP::CEDROOMRegularRemoteCommSAP(TEDROOMUInt32 maxConnections,
				TEDROOMUInt32 maxNumberOfPriorities,
				TEDROOMUInt32 maxNumberOfMessages,
				TEDROOMUInt32 commTasksStackSize,
				CEDROOMPackage * pInBufferPackage,
				CEDROOMPackage * pOutBufferPackage,
				CEDROOMRemoteConnectionInfo * remoteConnectionInfo,
				CEDROOMRegularRemoteCommSAPMemory * commSAPMemory) :
				CEDROOMRemoteCommSAP(maxConnections, commSAPMemory),
				m_MaxNumberOfPriorities(maxNumberOfPriorities),
				mp_OutBufferPackageMaxSize(commSAPMemory->m_OutBufferPackageMemorySize),
				mp_InBufferPackageMaxSize(commSAPMemory->m_InBufferPackageMemorySize),
				mp_RXConnectionInfo(remoteConnectionInfo),
#ifdef _EDROOM_IS_DEBUG_
				m_MsgQueueTX(maxNumberOfMessages, &this->m_CommTXTask, &this->m_Mutex,
					maxNumberOfPriorities, &commSAPMemory->m_QueueNodesPool,
					commSAPMemory->mp_QueueHeads, "Remote Comm SAP queue"),
				m_CommTXTask(EDROOMfunTXComm, "Remote Comm SAP TX Task",
						EDROOMprioNormal, commTasksStackSize),
		        m_CommRXTask(EDROOMfunRXComm, "Remote Comm SAP RX Task",
		        		EDROOMprioURGENT, commTasksStackSize)
#else
				m_MsgQueueTX(maxNumberOfMessages, &this->m_CommTXTask, &this->m_Mutex,
					maxNumberOfPriorities, &commSAPMemory->m_QueueNodesPool,
					commSAPMemory->mp_QueueHeads),
				m_CommTXTask(EDROOMfunTXComm, EDROOMprioNormal, commTasksStackSize),
		        m_CommRXTask(EDROOMfunRXComm, EDROOMprioURGENT, commTasksStackSize)
#endif
{
	mp_InBufferPackage = pInBufferPackage;
	mp_OutBufferPackage = pOutBufferPackage;
}

void CEDROOMRegularRemoteCommSAP::DeliverMsg(CEDROOMRemoteTXChannel * channel, CEDROOMMessage * message)
{
    this->m_Mutex.Wait();
    this->m_CommTXTask.SetMaxPrioMsg(EDROOMprioNormal);
    this->m_MsgQueueTX.In(message);
    this->m_Mutex.Signal();
}

Pr_TaskRV_t CEDROOMRegularRemoteCommSAP::EDROOMfunTXComm(Pr_TaskP_t)
{
    CEDROOMMessage * Msg = NULL;
    CEDROOMRemoteTXChannel * pChannel;
    CEDROOMRegularRemoteCommSAP * pCommSAP;


    Pr_Receive(&pCommSAP,sizeof(CEDROOMRegularRemoteCommSAP *));

    if (pCommSAP->initSend())
    {
        /* TODO Error! */
        while(1);
    }

    for (;;)
    {
        // Step 2: Out a message from the queue
		pCommSAP->m_Mutex.Wait();
        EDROOMFreeMessage(Msg); // Initially Msg == NULL

        //Cambio la prioridad de la tarea a la del siguiente mensaje
        //que hay en la cola (si no hay ninguno la prioridad sera la minima)
        //Esto permite que el resto de los actores tengan la oportunidad
        //de enviar sus mensajes mas prioritarios a este mismo actor

        //++ TODO: USAR UN MUTEX
        pCommSAP->m_MsgQueueTX.SetToMsgPriority();
		pCommSAP->m_Mutex.Signal(); //Libero aqui la exclusion mutua para que se haga efectiva

        pCommSAP->m_MsgQueueTX.Out(Msg); // Tomo un nuevo mensaje de la cola y hago que
        // Msg apunte a el.

        // Step 3: Decode and serialize message
        pChannel = (CEDROOMRemoteTXChannel *)(Msg->GetPInterface()->mp_Channel);

        pCommSAP->mp_OutBufferPackage->SetSenderComponentID(pChannel->GetSenderComponentID());
        pCommSAP->mp_OutBufferPackage->SetSenderInterfaceID(pChannel->GetSenderInterfaceID());
        pCommSAP->mp_OutBufferPackage->SetDestinationInterfaceID(pChannel->GetDestinationInterfaceID());
        pCommSAP->mp_OutBufferPackage->SetDestinationComponentID(pChannel->GetDestinationComponentID());
        pCommSAP->mp_OutBufferPackage->SetSignal(Msg->signal);
        pCommSAP->mp_OutBufferPackage->SetMessageType(Msg->type);
        pCommSAP->mp_OutBufferPackage->SetPriority(Msg->priority);
        pCommSAP->mp_OutBufferPackage->SetTimeStamp(0x123456);

        if (Msg->data)
        {
            pFunSerializeData funSerializeData = pChannel->GetSerializeFunction(Msg->signal);
            funSerializeData(Msg->data, pCommSAP->mp_OutBufferPackage->GetpRawData());
            pCommSAP->mp_OutBufferPackage->SetDataSize(Msg->GetMsgDataSize());

        }
        else
        {
            pCommSAP->mp_OutBufferPackage->SetDataSize(0);
        }

        // Step 4: Call the platform dependant function to send the message
        pCommSAP->send(pChannel->GetConnectionInfo(), pCommSAP->mp_OutBufferPackage); // Synchronous call

    }
}

Pr_TaskRV_t CEDROOMRegularRemoteCommSAP::EDROOMfunRXComm(Pr_TaskP_t)
{
    /* Step 1: Wait for the signal that indicates that all the interfaces
     *         have been registered */
    CEDROOMRegularRemoteCommSAP * pCommSAP;
    CEDROOMRemoteConnection * pRemoteConnection;

    Pr_Receive(&pCommSAP,sizeof(CEDROOMRegularRemoteCommSAP *));

    if (pCommSAP->initReceive())
    {
        /* TODO Error! */
        while(1);
    }

    /* Step 2: Prepare to receive the information of the incoming
     *         connections */

    /* CommSAP main loop */
    while(1)
    {
        pCommSAP->receive(pCommSAP->mp_InBufferPackage, pCommSAP->mp_InBufferPackageMaxSize);

        /* It seems to be a valid message. Now we shall check the
             * destination Interface ID */
        if ((pRemoteConnection =
            		pCommSAP->m_RemoteConnectionLocator.SearchFor(
            				pCommSAP->mp_InBufferPackage->GetDestinationComponentID(),
            				pCommSAP->mp_InBufferPackage->GetDestinationInterfaceID())) != NULL)
        {
        	/* Everything seems to be ok. Now we call the componentReceive
             * function of the RemoteRXChannel */
            pRemoteConnection->m_RXChannel.ComponentReceive(pCommSAP->mp_InBufferPackage->GetSignal(),
            		pCommSAP->mp_InBufferPackage->GetMessageType(),
            		pCommSAP->mp_InBufferPackage->GetPriority(),
            		pCommSAP->mp_InBufferPackage->GetpRawData(),
            		pCommSAP->mp_InBufferPackage->GetDataSize());
        }
        else
        {
                /* TODO: We have received a message with a wrong id */
        }
     }
}

TEDROOMWord32 CEDROOMRegularRemoteCommSAP::initService ()
{
    CEDROOMRemoteCommSAP * pCommSAP;

    pCommSAP = this;

    /* Step 1: Send the EDROOMRemoteCommSAP * to the comm task */
    Pr_Send(m_CommTXTask, &pCommSAP);
    Pr_Send(m_CommRXTask, &pCommSAP);

    return 0;
}

TEDROOMWord32 CEDROOMRegularRemoteCommSAP::endService(void)
{
    return 0;
}

void CEDROOMFragmentedPackagesPool::SetMemory(TEDROOMUInt32 dimension
			, void * pMessagePool
  			, TEDROOMBool * pMemoryMarks
  			, TEDROOMUInt32 elementSize)
{
	CEDROOMMemoryPool::SetMemory(dimension, pMessagePool
				, pMemoryMarks, elementSize);

}

CEDROOMFragmentedPackage * CEDROOMFragmentedPackagesPool::AllocData()
{
	return (CEDROOMFragmentedPackage * )CEDROOMMemoryPool::AllocData();
}

CEDROOMFragmentedRemoteCommSAP::CEDROOMFragmentedRemoteCommSAP(
		TEDROOMUInt32 maxConnections,
		TEDROOMUInt32 maxNumberOfPriorities,
		TEDROOMUInt32 maxNumberOfMessages,
		TEDROOMUInt32 commTasksStackSize,
		CEDROOMRemoteConnectionInfo * localConnectionInfo,
		CEDROOMRemoteConnectionInfo * remoteConnectionInfo,
		pFunGetConnectionID getConnectionIDFun,
		CEDROOMFragmentedRemoteCommSAPMemory * commSAPMemory) :

			CEDROOMRemoteCommSAP(maxConnections, commSAPMemory),

			m_MaxNumberOfConnections(maxConnections),
			m_MaxNumberOfPriorities(maxNumberOfPriorities),

			mp_OutPriorityPackages(commSAPMemory->mp_OutPriorityPackages),
			mp_InNodePriorityPackages(commSAPMemory->mp_InNodePriorityPackages),

			mp_InPackageFragment(commSAPMemory->mp_InFragment),
			mp_OutPackageFragment(commSAPMemory->mp_OutFragment),

			mp_OutPackagesPool(&commSAPMemory->m_OutPackagesPool),
			mp_InPackagesPool(&commSAPMemory->m_InPackagesPool),

			mp_LocalConnectionInfo(localConnectionInfo),
			mp_RemoteConnectionInfo(remoteConnectionInfo),

			mp_GetConnectionIDFun(getConnectionIDFun),

#ifdef _EDROOM_IS_DEBUG_
			m_MsgQueueTX(maxNumberOfMessages, &this->m_CommTXTask, &this->m_Mutex,
				maxNumberOfPriorities, &commSAPMemory->m_QueueNodesPool,
				commSAPMemory->mp_QueueHeads, "Remote Comm SAP queue"),
			m_CommTXTask(EDROOMfunTXComm, "Remote Comm SAP TX Task",
					EDROOMprioNormal, commTasksStackSize),
	        m_CommRXTask(EDROOMfunRXComm, "Remote Comm SAP RX Task",
	        		EDROOMprioURGENT, commTasksStackSize)
#else
			m_MsgQueueTX(maxNumberOfMessages, &this->m_CommTXTask, &this->m_Mutex,
				maxNumberOfPriorities, &commSAPMemory->m_QueueNodesPool,
				commSAPMemory->mp_QueueHeads),
			m_CommTXTask(EDROOMfunTXComm, EDROOMprioNormal, commTasksStackSize),
	        m_CommRXTask(EDROOMfunRXComm, EDROOMprioURGENT, commTasksStackSize)
#endif
{

}

void CEDROOMFragmentedRemoteCommSAP::DeliverMsg(CEDROOMRemoteTXChannel * channel, CEDROOMMessage * message)
{
	this->m_Mutex.Wait();
//	this->m_CommTXTask.SetMaxPrioMsg(EDROOMprioNormal);
	this->m_MsgQueueTX.In(message);
	this->m_Mutex.Signal();
}

Pr_TaskRV_t CEDROOMFragmentedRemoteCommSAP::EDROOMfunTXComm(Pr_TaskP_t)
{

	CEDROOMMessage * Msg = NULL;
	CEDROOMRemoteTXChannel * pChannel;
	CEDROOMFragmentedRemoteCommSAP * pCommSAP;
	TEDROOMPriority priority;
	TEDROOMPriority pendingPriority;


	Pr_Receive(&pCommSAP,sizeof(CEDROOMFragmentedRemoteCommSAP *));

	if (pCommSAP->initSend())
	{
		/* TODO Error! */
		while(1);
	}

	for (;;)
	{
		pCommSAP->m_Mutex.Wait();
		EDROOMFreeMessage(Msg); // Initially Msg == NULL

		//Cambio la prioridad de la tarea a la del siguiente mensaje
		//que hay en la cola (si no hay ninguno la prioridad sera la minima)
		//Esto permite que el resto de los actores tengan la oportunidad
		//de enviar sus mensajes mas prioritarios a este mismo actor

		//++ TODO: USAR UN MUTEX
		pCommSAP->m_MsgQueueTX.SetToMsgPriority();
		pCommSAP->m_Mutex.Signal(); //Libero aqui la exclusion mutua para que se haga efectiva

		pCommSAP->m_MsgQueueTX.Out(Msg); // Tomo un nuevo mensaje de la cola y hago que
		// Msg apunte a el.

		// Get the priority of the message
		priority = Msg->priority;

		// Get one package from the pool of packages
	    pCommSAP->mp_OutPriorityPackages[priority] = pCommSAP->mp_OutPackagesPool->AllocData();

        // Step 3: Decode and serialize message
        pChannel = (CEDROOMRemoteTXChannel *)(Msg->GetPInterface()->mp_Channel);

        pCommSAP->mp_OutPriorityPackages[priority]->SetSenderComponentID(pChannel->GetSenderComponentID());
        pCommSAP->mp_OutPriorityPackages[priority]->SetSenderInterfaceID(pChannel->GetSenderInterfaceID());
        pCommSAP->mp_OutPriorityPackages[priority]->SetDestinationInterfaceID(pChannel->GetDestinationInterfaceID());
        pCommSAP->mp_OutPriorityPackages[priority]->SetDestinationComponentID(pChannel->GetDestinationComponentID());
        pCommSAP->mp_OutPriorityPackages[priority]->SetSignal(Msg->signal);
        pCommSAP->mp_OutPriorityPackages[priority]->SetMessageType(Msg->type);
        pCommSAP->mp_OutPriorityPackages[priority]->SetPriority(Msg->priority);

        // TODO: ver como rellenamos el timestamp
        pCommSAP->mp_OutPriorityPackages[priority]->SetTimeStamp(0x88234588);

        if (Msg->data)
        {
            pFunSerializeData funSerializeData = pChannel->GetSerializeFunction(Msg->signal);
            void * pRawData = pCommSAP->mp_OutPriorityPackages[priority]->GetpRawData();
            funSerializeData(Msg->data, pRawData);
            pCommSAP->mp_OutPriorityPackages[priority]->SetDataSize(Msg->GetMsgDataSize());
 //           DEBUG("MsgSize = %d", Msg->GetMsgDataSize());
        }
        else
        {
            pCommSAP->mp_OutPriorityPackages[priority]->SetDataSize(0);
        }

        // Reset the fragment index
        pCommSAP->mp_OutPriorityPackages[priority]->ResetFragmentIndex();

		//Step 4: Get the first fragment to send
		pCommSAP->mp_OutPriorityPackages[priority]->GetFragment(pCommSAP->mp_OutPackageFragment);

		// TODO: ver si tenemos que comprobar que el tamaño del fragmento sea != 0

		// Step 5: Call the platform dependant function to send the fragment
		pCommSAP->send(pChannel->GetConnectionInfo(),
				pCommSAP->mp_OutPriorityPackages[priority],
				pCommSAP->mp_OutPackageFragment); // Synchronous call
		// Now we have to send the rest of the fragments

		if (pCommSAP->mp_OutPackageFragment->IsLast())
		{
			// First, we have to free the package
			pCommSAP->mp_OutPackagesPool->FreeData(pCommSAP->mp_OutPriorityPackages[priority]);
			// And then we have to nullify the entry of the priority table
			pCommSAP->mp_OutPriorityPackages[priority] = NULL;
			continue;
		}

		for(;;)
		{
			// Check if there is any pending message with a priority higher
			// than the one we are sending...
			pCommSAP->m_Mutex.Wait();
			pendingPriority =
					pCommSAP->m_MsgQueueTX.GetMaxQueuedMsgPriority();
			if (pendingPriority < priority)
			{
				// We have to start sending the new message!
				// We have to free the previous message
				EDROOMFreeMessage(Msg);
				pCommSAP->m_Mutex.Signal();
				// We have to obtain the message.
				// IF EVERYTHING IS OK, THIS CALL SHOULD NEVER BLOCK
				pCommSAP->m_MsgQueueTX.Out(Msg);

				// Get the priority of the message
				priority = Msg->priority;

				// Get one package from the pool of packages
				pCommSAP->mp_OutPriorityPackages[priority] = pCommSAP->mp_OutPackagesPool->AllocData();

		        // Step 3: Decode and serialize message
		        pChannel = (CEDROOMRemoteTXChannel *)(Msg->GetPInterface()->mp_Channel);

		        pCommSAP->mp_OutPriorityPackages[priority]->SetSenderComponentID(pChannel->GetSenderComponentID());
		        pCommSAP->mp_OutPriorityPackages[priority]->SetSenderInterfaceID(pChannel->GetSenderInterfaceID());
		        pCommSAP->mp_OutPriorityPackages[priority]->SetDestinationInterfaceID(pChannel->GetDestinationInterfaceID());
		        pCommSAP->mp_OutPriorityPackages[priority]->SetDestinationComponentID(pChannel->GetDestinationComponentID());
		        pCommSAP->mp_OutPriorityPackages[priority]->SetSignal(Msg->signal);
		        pCommSAP->mp_OutPriorityPackages[priority]->SetMessageType(Msg->type);
		        pCommSAP->mp_OutPriorityPackages[priority]->SetPriority(Msg->priority);

		        // TODO: ver como rellenamos el timestamp
		        pCommSAP->mp_OutPriorityPackages[priority]->SetTimeStamp(0x8888);

		        if (Msg->data)
		        {
		            pFunSerializeData funSerializeData = pChannel->GetSerializeFunction(Msg->signal);
		            funSerializeData(Msg->data, pCommSAP->mp_OutPriorityPackages[priority]->GetpRawData());
		            pCommSAP->mp_OutPriorityPackages[priority]->SetDataSize(Msg->GetMsgDataSize());

		        }
		        else
		        {
		            pCommSAP->mp_OutPriorityPackages[priority]->SetDataSize(0);
		        }

		        // Reset the fragment index
		        pCommSAP->mp_OutPriorityPackages[priority]->ResetFragmentIndex();
			}
			else
			{
				pCommSAP->m_Mutex.Signal();
			}
			//Step 4: Get the first fragment to send
			pCommSAP->mp_OutPriorityPackages[priority]->GetFragment(pCommSAP->mp_OutPackageFragment);

			// TODO: ver si tenemos que comprobar que el tamaño del fragmento sea != 0

			// Step 5: Call the platform dependant function to send the fragment
			pCommSAP->send(pChannel->GetConnectionInfo(),
					pCommSAP->mp_OutPriorityPackages[priority],
					pCommSAP->mp_OutPackageFragment); // Synchronous call

			if (pCommSAP->mp_OutPackageFragment->IsLast())
			{
				// Now we have to check if we are leaving some unsent packages...
				// First, we have to free the package
				pCommSAP->mp_OutPackagesPool->FreeData(pCommSAP->mp_OutPriorityPackages[priority]);
				// And then we have to nullify the entry of the priority table
				pCommSAP->mp_OutPriorityPackages[priority] = NULL;
				// TODO: Revisar prioridades a ver si no la estamos liando
				for (TEDROOMUInt32 i = EDROOMprioURGENT; i < pCommSAP->m_MaxNumberOfPriorities; i++)
				{
					if (pCommSAP->mp_OutPriorityPackages[i-EDROOMprioURGENT] != NULL)
					{
						priority = (TEDROOMPriority)i;
						continue;
					}
				}
				break;
			}


		}
	}

}
Pr_TaskRV_t CEDROOMFragmentedRemoteCommSAP::EDROOMfunRXComm(Pr_TaskP_t)
{
    /* Step 1: Wait for the signal that indicates that all the interfaces
     *         have been registered */
	CEDROOMFragmentedRemoteCommSAP * pCommSAP;
    CEDROOMRemoteConnection * pRemoteConnection;
 //   CEDROOMFragmentedPackage * package;
    TEDROOMConnectionID nodeID;
    TEDROOMPriority priority;

    Pr_Receive(&pCommSAP,sizeof(CEDROOMFragmentedRemoteCommSAP *));


    //if (pCommSAP->initReceive())
    //{
        /* TODO Error! */
    	//PANIC(__FILE__,__LINE__,"Error in initReceive()");
    //}

    //DEBUG("initReceive");
    /* Step 2: Prepare to receive the information of the incoming
     *         connections */

    /* CommSAP main loop */
    while(1)
    {

    	// wait till receive one fragment
        pCommSAP->receive(pCommSAP->mp_InPackageFragment,
        		pCommSAP->mp_RemoteConnectionInfo,
        		(TEDROOMPriority *)&priority);
        nodeID = pCommSAP->mp_GetConnectionIDFun(pCommSAP->mp_RemoteConnectionInfo);
//		DEBUG("NodeID = %d, priority = %d", nodeID, priority);
		// We have to check if there was already a package stored in the
		// array
		if (pCommSAP->mp_InNodePriorityPackages[nodeID][priority] == NULL)
		{

			pCommSAP->mp_InPackageFragment->SetFirst();
			pCommSAP->mp_InPackageFragment->SetIndex((TEDROOMUInt32)0);

			CEDROOMFragmentedPackage * aux = pCommSAP->mp_InPackagesPool->AllocData();
//			DEBUG("packet allocated in %p", aux);

//			DEBUG("InPackagesPool is in %p", pCommSAP->mp_InPackagesPool);
			// There was no package, so we have to get a new one
			pCommSAP->mp_InNodePriorityPackages[nodeID][priority] = aux;
		}
		else
		{
			// TODO: there was already a package! :(
			//TODO:	ESTO DE ABAJO ES PARA PROBAR
			pCommSAP->mp_InPackageFragment->SetLast();
		}
//		DEBUG("sigo por aqui");
        // If the fragment is the first one
		if (pCommSAP->mp_InPackageFragment->IsFirst())
		{
        	// We have to reset the index and store the fragment
        	pCommSAP->mp_InNodePriorityPackages[nodeID][priority]->ResetFragmentIndex();
        	pCommSAP->mp_InNodePriorityPackages[nodeID][priority]->PutFragment(
        			pCommSAP->mp_InPackageFragment);
        	continue;
        }

       	if (pCommSAP->mp_InNodePriorityPackages[nodeID][priority] == NULL)
       	{
 //      		PANIC(__FILE__,__LINE__,"Null package");
       		// TODO: there was no a package! :(
       		// continue;
       	}

       	pCommSAP->mp_InNodePriorityPackages[nodeID][priority]->PutFragment(
       			pCommSAP->mp_InPackageFragment);

        if (pCommSAP->mp_InPackageFragment->IsLast())
        {
//        	DEBUG("it was the last fragment...");
            if ((pRemoteConnection =
                		pCommSAP->m_RemoteConnectionLocator.SearchFor(
                				pCommSAP->mp_InNodePriorityPackages[nodeID][priority]->GetDestinationComponentID(),
                				pCommSAP->mp_InNodePriorityPackages[nodeID][priority]->GetDestinationInterfaceID())) != NULL)
            {
            	/* Everything seems to be ok. Now we call the componentReceive
                 * function of the RemoteRXChannel */
                pRemoteConnection->m_RXChannel.ComponentReceive(
                		pCommSAP->mp_InNodePriorityPackages[nodeID][priority]->GetSignal(),
                		pCommSAP->mp_InNodePriorityPackages[nodeID][priority]->GetMessageType(),
                		pCommSAP->mp_InNodePriorityPackages[nodeID][priority]->GetPriority(),
                		pCommSAP->mp_InNodePriorityPackages[nodeID][priority]->GetpRawData(),
                		pCommSAP->mp_InNodePriorityPackages[nodeID][priority]->GetDataSize());
            }
 //           DEBUG("free the package");
            pCommSAP->mp_InPackagesPool->FreeData(pCommSAP->mp_InNodePriorityPackages[nodeID][priority]);
			// And then we have to nullify the entry of the priority table
			pCommSAP->mp_InNodePriorityPackages[nodeID][priority] = NULL;
        }
     }

}

TEDROOMWord32 CEDROOMFragmentedRemoteCommSAP::initService (void)
{
	CEDROOMRemoteCommSAP * pCommSAP;

	pCommSAP = this;

	/* Step 1: Send the EDROOMRemoteCommSAP * to the comm task */
	Pr_Send(m_CommTXTask, &pCommSAP);
	Pr_Send(m_CommRXTask, &pCommSAP);


	return 0;
}

TEDROOMWord32 CEDROOMFragmentedRemoteCommSAP::endService (void)
{
	return 0;
}


/*!
 * \brief EDROOMComponent cpp (edroom services library) 
 * 
 * \author Oscar Rodrguez Polo
 * \date $Date: 2010-03-04 09:08:16 $
 * \Version $Revision: 1.1.2.2 $
 *
 * $Log: edroomcomponent.cpp,v $
 * Revision 1.1.2.2  2010-03-04 09:08:16  opolo
 * Changed the names of the attributes
 *
 * Revision 1.1.2.1  2010-02-15 10:09:17  opolo
 * actualizados los nombres de los archivos y servicios
 *
 * Revision 1.1.4.3  2006/11/09 15:23:12  opolo
 * Use the new name of the classes that manage the pools
 * 	EDROOMPool EDROOMMemoryPool and EDROOMProtectedMemoryPool
 *
 * Revision 1.1.4.2  2006/10/18 18:31:51  opolo
 * Add Log
 *
 *
 * Revision 1.1.4.1  2006/10/18 18:07:20  opolo
 * *** empty log message ***
 * 
 */



#ifdef _EDROOM_IS_DEBUG_

CEDROOMstream EDROOMFError("FError");
CEDROOMDummyStream EDROOMFDeb("FDeb");
CEDROOMstream cout("Cout");

#endif

//**************************************************************************
// IMPLEMENTACION DE LOS COMPONENTES DE UN MODELO EDROOM BASADAS EN LAS
// PRIMITIVAS DE TIEMPO REAL DEFINIDAS EN prim_pp.h
//**************************************************************************

//*****************************************************************//
//                                                      CLASE Componente                                //
//*****************************************************************//


//******************** CONSTRUCTOR ************************//


// DEFINICION DEL CONSTRUCTOR DE LA CLASE EDROOMComponent




#ifdef _EDROOM_IS_DEBUG_

CEDROOMComponent::CEDROOMComponent(		const char * const pname,
										TEDROOMComponentID componentID,
										unsigned numPri, unsigned numCon,int numMaxM,
										 TEDROOMPriority prioTask,unsigned stack

										,CEDROOMComponentMemory * pComponentMemory



										 ): m_ComponentID(componentID)
										 ,m_Mutex("Sem Component")
										 ,m_SynchrMsgPool(&m_SynchrMsgOut)
							
										 		 
															// Reservo
															// la cola de mensajes con
															// por numMaxMens y un numero de
															// prioridades dado por numPrior


										 ,m_ComponentTask(EDROOMComponentTask,(char *) pname,prioTask,stack)
										 ,m_MsgQueue(numMaxM, &m_ComponentTask, &this->m_Mutex, numPri,
												 &pComponentMemory->m_QueueNodesPool,
												 pComponentMemory->mp_QueueHeads, pname)
										
										 ,EDROOMName(pname)
									




#else

CEDROOMComponent::CEDROOMComponent( TEDROOMComponentID componentID, unsigned numPri, unsigned numCon,int numMaxM,
										 TEDROOMPriority prioTask,unsigned stack

										,CEDROOMComponentMemory * pComponentMemory	 ):
										 m_ComponentID(componentID)
										 ,m_SynchrMsgPool(&m_SynchrMsgOut)
										 ,m_ComponentTask(EDROOMComponentTask,prioTask,stack)
										 ,m_MsgQueue(numMaxM, &m_ComponentTask, &this->m_Mutex, numPri,
												 &pComponentMemory->m_QueueNodesPool,
												 pComponentMemory->mp_QueueHeads)
										

#endif



										 {


	mp_ComponentTask=&m_ComponentTask; // Todavia no tiene una tarea que ejecute su comportamiento.

	m_MaxNumMsgs=numMaxM; // Numero maximo de mensajes que mantendra este component
							// en su cola de mensajes

	mp_MsgPool = &pComponentMemory->m_MessagesPool; // Tomo la memoria reservada

	m_NumConections=numCon;        // Numero de conexiones entre los componentes componentes
								// de ese component, esta determinado por el diseo del
								// component.

	m_NumMsgPrio=numPri;  // Numero de prioridades de los mensajes que trata.

	Msg=NULL;               //Inicialmente no hay ningun mensaje

	MsgBack=NULL;               //Inicialmente no hay ningun mensaje




#ifdef _EDROOM_SYSTEM_CLOSE

	m_IsFinished=0;   // La tarea no ha terminado

#endif

#ifdef _EDROOM_HAND_EXCEP_

	m_IsNewException=false;

#endif


#ifndef _EDROOM_NO_INHERIT_MSG

    mp_ComponentIsLockingMe=NULL;
#endif


#ifdef __EDROOMSL_2010				
	mpp_IRQInterfaces=pComponentMemory->mpp_IRQInterfaces;
	mpp_TimingInterfaces=pComponentMemory->mpp_TimingInterfaces;
#endif


}

					// para liberar la memoria del component
					// No se hace en el constructor para permitir que se libere la
					// de forma distribuida


#ifdef _EDROOM_SYSTEM_CLOSE

void CEDROOMComponent::FreeMem(){

	  m_Mutex.Wait();
	  EDROOMFreeMessage(Msg);

								  //Libero la memoria reservada
	  m_MsgQueue.FreeMem(); // PRIMERO LA COLA DE MENSAJES

	  m_IsFinished=1;

	  m_Mutex.Signal();


	}




//******************** METODOS PUBLICOS ************************//

// DEFINICION DEL METODO EDROOMIsComponentFinished DE LA CLASE Component



TEDROOMBool CEDROOMComponent::EDROOMIsComponentFinished(){
		return (m_IsFinished);
}


#endif

// DEFINICION DEL DESTRUCTOR DE LA CLASE EDROOMComponent


CEDROOMComponent::~CEDROOMComponent(){

}



void CEDROOMComponent::EDROOMDestroy(){


	  CEDROOMMessage *Msg;

	  m_Mutex.Wait();

	  Msg=mp_MsgPool->AllocData(); //Tomo un mensaje nuevo

	  Msg->signal=1 ;   // EDROOMDestroy

	  Msg->mp_MsgPool=mp_MsgPool;

	  //No hay dato enviado
	  Msg->data=NULL;

	  //No hay manejador de memoria
	  Msg->mp_DataPool=NULL;

	  //Prioridad del mensaje establecida por defecto

	  Msg->priority=EDROOMprioVeryHigh;

      m_ComponentTask.SetMaxPrioTmp( EDROOMprioVeryHigh);

	  m_MsgQueue.In(Msg); // METO EN LA COLA DE MENSAJES

	  m_Mutex.Signal();


}

// DEFINICION DEL METODO Start DE LA CLASE CEDROOMComponent

// El metodo Start crea una tarea a partir de la funcion miembro Comportamiento

// El parametro prioTask es la prioridad inicial de las tareas



int CEDROOMComponent::EDROOMStart(){
	CEDROOMComponent *ap_component;

	ap_component=this; // Le manda un puntero a este component a la tarea para
						// que ejecute el comportamiento

	Pr_Send(*mp_ComponentTask,&ap_component);


	return (1); // Sin errores
}



//******************** METODOS PUBLICOS ************************//

// DEFINICION DEL METODO NewMsg DE LA CLASE CEDROOMComponent

  // Funcion miembro que permite sacar un mensaje  de la cola y hace que Msg
 // apunte a ese mensaje a la vez que libera la memoria del anterior
 // mensaje al que estaba apuntando Msg

void CEDROOMComponent::EDROOMNewMsg(){

	 do{


		//Si no libero la memoria del mensaje anterior
		m_Mutex.Wait();
		EDROOMFreeMessage(Msg);

			//Cambio la prioridad de la tarea a la del siguiente mensaje
			//que hay en la cola (si no hay ninguno la prioridad sera la minima)
			//Esto permite que el resto de los componentes tengan la oportunidad
			//de enviar sus mensajes mas prioritarios a este mismo component

		m_MsgQueue.SetToMsgPriority();
		m_Mutex.Signal(); //Libero aqui la exclusion mutua para que se haga efectiva
								//la posible entrada de otros


		m_MsgQueue.Out(Msg); // Tomo un nuevo mensaje de la cola y hago que
									 // Msg apunte a el.

	 }while(Msg->IsCancelled());  // Si el mensaje esta cancelado repito la operacion

}

//******************** METODOS PUBLICOS ************************//

// DEFINICION DEL METODO NewMsgWithExc DE LA CLASE CEDROOMComponent

  //Anade a NewMsg la capacidad de tratar con interrupciones

#ifdef _EDROOM_HAND_EXCEP_

void CEDROOMComponent::EDROOMNewMsgWithExc(){

	 do{

		//Si no libero la memoria del mensaje anterior
		m_Mutex.Wait();

		if (m_IsNewException){

			MsgExc=Msg;

			Msg=mp_MsgPool->AllocData();
			Msg->signal= 2;  // EDROOMException es siempre 2
			Msg->data=NULL;
			Msg->mp_DataPool=NULL;
 			m_IsNewException=false;

			m_Mutex.Signal(); //Libero aqui la exclusion mutua para que se haga efectiva
								//la posible entrada de otros

		}
		else {
			EDROOMFreeMessage(Msg);


			//Cambio la prioridad de la tarea a la del siguiente mensaje
			//que hay en la cola (si no hay ninguno la prioridad sera la minima)
			//Esto permite que el resto de los componentes tengan la oportunidad
			//de enviar sus mensajes mas prioritarios a este mismo component

			m_MsgQueue.SetToMsgPriority();

			m_Mutex.Signal(); //Libero aqui la exclusion mutua para que se haga efectiva
								//la posible entrada de otros

								// Lo puedo hacer antes del MsgOut porque este tambien respeta la exclusion
                        //Mutua

			m_MsgQueue.Out(Msg); // Tomo un nuevo mensaje de la cola y hago que
									 // Msg apunte a el.


		}

	 }while(Msg->IsCancelled());  // Si el mensaje esta cancelado repito la operacion

}

#endif


/**
//EDROOMTraceTrans
// Include info to Trace the execution
*/

#ifdef _EDROOM_IS_DEBUG_

void CEDROOMComponent::EDROOMTraceTrans(TEDROOMTransId & TransId, TEDROOMSignal signal){

        Pr_Time currentTime;

        m_Mutex.Wait();  //Take the URGENT prio to avoid the preemption
        mp_ComponentTask->SetMaxPrioTmp(EDROOMprioURGENT);


        currentTime.GetTime();
        EDROOMFDeb << "\tEndEvent\n"<<"MsgIn"  ;
        EDROOMFDeb << "\t" << currentTime.GetTicks();
        EDROOMFDeb << "\t" << EDROOMName  ;
        EDROOMFDeb << "\t" << signal;
        EDROOMFDeb << "\t" << TransId.localId ;
        EDROOMFDeb << "\t" << TransId.distanceToContext;

        EDROOMFDeb.close();
//        EDROOMFDeb.open("roomfdeb.lst",ios::app) ;
        EDROOMFDeb.reopen() ;

        mp_ComponentTask->RestorePrioMsg(); //Restore the situation
        m_Mutex.Signal();

}

void CEDROOMComponent::EDROOMTraceStateEntry(){

        Pr_Time currentTime;

        m_Mutex.Wait();  //Take the URGENT prio to avoid the preemption
        mp_ComponentTask->SetMaxPrioTmp(EDROOMprioURGENT);
        currentTime.GetTime();

        EDROOMFDeb << "\t" << EDROOMName  ;
        EDROOMFDeb << "\t" << currentTime.GetTicks();
        
        EDROOMFDeb.close();
        EDROOMFDeb.reopen() ;

        mp_ComponentTask->RestorePrioMsg(); //Restore the situation
        m_Mutex.Signal();

}

void CEDROOMComponent::EDROOMTraceStateExit(){

        Pr_Time currentTime;

        m_Mutex.Wait();  //Take the URGENT prio to avoid the preemption
        mp_ComponentTask->SetMaxPrioTmp(EDROOMprioURGENT);
        currentTime.GetTime();

        EDROOMFDeb << "\t" << EDROOMName  ;
        EDROOMFDeb << "\t" << currentTime.GetTicks();
        
        EDROOMFDeb.close();
        EDROOMFDeb.reopen() ;

        mp_ComponentTask->RestorePrioMsg(); //Restore the situation
        m_Mutex.Signal();

}
#endif



#ifndef _EDROOM_NO_INHERIT_MSG

/**
//PrioInheritanceInSendMsg
// Fix the priority and Propagate to the mp_ComponentIsLockingMe
*/

void CEDROOMComponent::PrioInheritanceInSendMsg( TEDROOMPriority  priority){
    mp_ComponentTask->SetMaxPrioMsg(priority);
    //Propagate the priority to avoid the priority inversion
    if(mp_ComponentIsLockingMe){
            mp_ComponentIsLockingMe->m_Mutex.Wait();
            mp_ComponentIsLockingMe->PrioInheritanceInSendMsg(priority);
            mp_ComponentIsLockingMe->m_Mutex.Signal();

    }

}

/**
//PrioInheritanceInInvokeMsg
// Fix the priority and Propagate to the mp_ComponentIsLockingMe
// Check if there is Interblock
*/

bool CEDROOMComponent::PrioInheritanceInInvokeMsg( CEDROOMComponent * pComponent
												, TEDROOMPriority  priority){
    bool InterBlock;

    mp_ComponentTask->SetMaxPrioMsg(priority);
    
    //Propagate the priority to avoid the priority inversion
    if(mp_ComponentIsLockingMe){
            if(mp_ComponentIsLockingMe!=pComponent){
                    mp_ComponentIsLockingMe->m_Mutex.Wait();
                    InterBlock=mp_ComponentIsLockingMe->PrioInheritanceInInvokeMsg(pComponent, priority);
                    mp_ComponentIsLockingMe->m_Mutex.Signal();
            }else InterBlock=true;

    }else
            InterBlock=false;

    return  InterBlock;

}

#endif


//******************    FUNCIONES AMIGAS    ***************************

//                                                                       tar_Component

// permite crear las tareas que  ejecutan el comportamiento de los componentes

#ifdef _EDROOM_TASK_POSIX_
	void * CEDROOMComponent::EDROOMComponentTask(void * paramDumy){

#else

	Pr_TaskRV_t CEDROOMComponent::EDROOMComponentTask(Pr_TaskP_t){
#endif

	CEDROOMComponent* ap_component;
	Pr_Receive(&ap_component,sizeof(CEDROOMComponent*));
	ap_component->EDROOMBehaviour();

#ifdef _EDROOM_SYSTEM_CLOSE

	ap_component->FreeMem();

#endif


}


//*****************************************************************//
//                                    CLASE CEDROOMComponentMemory                                //
//*****************************************************************//


void CEDROOMComponentMemory::SetMemory(
				TEDROOMUInt32 messagesNumber_,CEDROOMMessage  * MessagesMem_
										, TEDROOMBool *  MessagesMemMarks_
				,CEDROOMQueue::CQueueNode * QueueNodesMem_
										, TEDROOMBool *  QueueNodesMemMarks_
				,CEDROOMQueue::CQueueHead *QueueHeadsMem_

#ifdef __EDROOMSL_2010				
				,CEDROOMIRQInterface ** pp_IRQInterfaces
				,CEDROOMTimingInterface ** pp_TimingInterfaces){
#else
				){

#endif				

				m_MessagesPool.SetMemory(messagesNumber_, MessagesMem_
														, MessagesMemMarks_);
				m_QueueNodesPool.SetMemory(messagesNumber_, QueueNodesMem_
														, QueueNodesMemMarks_);


				mp_QueueHeads=QueueHeadsMem_;

#ifdef __EDROOMSL_2010				
				mpp_IRQInterfaces=pp_IRQInterfaces;
				mpp_TimingInterfaces=pp_TimingInterfaces;
#endif				

}






/*!
 * \brief edroomexcept cpp (edroom services library) 
 * 
 * \author Oscar Rodrguez Polo
 * \date $Date: 2010-02-15 10:09:17 $
 * \Version $Revision: 1.1.4.3 $
 *
 * $Log: edroomexcept.cpp,v $
 * Revision 1.1.4.3  2010-02-15 10:09:17  opolo
 * actualizados los nombres de los archivos y servicios
 *
 * Revision 1.1.4.2  2006/10/18 18:31:51  opolo
 * Add Log
 *
 *
 * Revision 1.1.4.1  2006/10/18 18:07:20  opolo
 * *** empty log message ***
 * 
 
 */


#ifdef _EDROOM_HAND_EXCEP_

CEDROOMExceptionSAP::CEDROOMExceptionSAP(CEDROOMComponent *pComponent){

	mp_Component=pComponent;

};

void CEDROOMExceptionSAP::NewException(){
	mp_Component->m_Mutex.Wait();
	mp_Component->m_IsNewException=true;

   #ifdef _EDROOM_NO_INHERIT_MSG

	mp_Component->m_ComponentTask.SetMaxPrioMsg(EDROOMprioURGENT);

	#else

		mp_Component->PrioInheritanceInSendMsg(EDROOMprioURGENT);

	#endif

	mp_Component->m_Mutex.Signal();

	//Cambiar prioridad a URGENTE?

}


#endif
